﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-慢慢来-最新评论</title><link>http://www.cppblog.com/findingworld/CommentsRSS.aspx</link><description>C++绝对是个好东西</description><language>zh-cn</language><pubDate>Sat, 06 Mar 2010 16:45:55 GMT</pubDate><lastBuildDate>Sat, 06 Mar 2010 16:45:55 GMT</lastBuildDate><generator>cnblogs</generator><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109083</link><dc:creator>luckycat</dc:creator><author>luckycat</author><pubDate>Sat, 06 Mar 2010 15:15:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109083</guid><description><![CDATA[@小苏<br>VC6我这里没有，我上面的输出是在VC2008下的测试结果，你换用VC2005/2008再试试.<br>我的建议是学习C++就不要用VC6了，可以用VC2005/2008.<br>如果你想用一个轻量级的环境学习C++，MinGW Studio，<br>wxDev-Cpp , CodeBlocks , CodeLite 都是不错的选择.<br><img src ="http://www.cppblog.com/findingworld/aggbug/109083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">luckycat</a> 2010-03-06 23:15 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109083#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109081</link><dc:creator>luckycat</dc:creator><author>luckycat</author><pubDate>Sat, 06 Mar 2010 15:10:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109081</guid><description><![CDATA[@小苏<br>为了更好的理解我上面的分析，你可以打开VC2005/VC2008(我这里是VC2008)的单步调试，<br>在调试模式下的&quot;自动窗口&quot;(位于IDE下方).<br>观察memset 前后&quot;man -&gt; strName -&gt; _Bx -&gt; _Ptr&quot;的值的变化<br>_Ptr 实际上就是std::string内部用于存储字符串的堆内存缓冲区的地址,也相当于我上面提到的 m_pCharBuffer<img src ="http://www.cppblog.com/findingworld/aggbug/109081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">luckycat</a> 2010-03-06 23:10 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109081#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109082</link><dc:creator>小苏</dc:creator><author>小苏</author><pubDate>Sat, 06 Mar 2010 15:10:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109082</guid><description><![CDATA[@luckycat<br><br>我的测试结果是：<br>before memset: char buffer address( heap address ) to store string = 0000000 , <br>size = 0 , capacity = 0 <br>after memset: char buffer address( heap address ) to store string = 00000000 , <br>size = 0 , capacity = 0 <br><br>这里没法贴图，我的QQ是270083015，比这里讨论快一点<br>我用的VC6 我想这是我的内存没有增长的原因吧。<br><img src ="http://www.cppblog.com/findingworld/aggbug/109082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">小苏</a> 2010-03-06 23:10 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109082#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109077</link><dc:creator>luckycat</dc:creator><author>luckycat</author><pubDate>Sat, 06 Mar 2010 14:50:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109077</guid><description><![CDATA[@小苏<br>在阅读下面的分析之前，希望你对&quot;C++对象的内部布局&quot;有一定的了解.<br>既然你也发现了内存泄漏的情况，那么你再用下面的测试代码运行一下:<br><br><br><br>#include &quot;Windows.h&quot; <br><br>#include &lt;string&gt; <br>#include &lt;cstring&gt; <br>#include &lt;cstdlib&gt; <br><br>using namespace std; <br><br>typedef unsigned int UINT32; <br>typedef unsigned short UINT16; <br><br>typedef struct structMan <br>{ <br>	UINT32 sexType; //ENUM_SEXY_TYPE <br>	UINT16 usAge; <br>	string strName; <br>	string strAddress; <br><br>	bool operator &lt; (const structMan &amp;man) const <br>	{ <br>		return usAge &lt; man.usAge; <br>	} <br><br>	bool operator &gt; (const structMan &amp;man) const <br>	{ <br>		return usAge &gt; man.usAge; <br>	} <br>}MAN; <br><br>int main( int argc , char *argv[] ) <br>{ <br><br>	while( true ) <br>	{ <br>		MAN man; <br>		fprintf( stdout , &quot;before memset:  char buffer address( heap address ) to store string = %p , size = %lu , capacity = %lu\n&quot; , \<br>				 *reinterpret_cast&lt; const int* &gt;( man.strName.c_str() ) , \<br>				 man.strName.size() , man.strName.capacity() );<br>		memset( &amp;man , 0 , sizeof( MAN ) );<br>		fprintf( stdout , &quot;after memset:  char buffer address( heap address ) to store string = %p , size = %lu , capacity = %lu\n\n\n&quot; , \<br>				 *reinterpret_cast&lt; const int* &gt;( man.strName.c_str() ) , \<br>				 man.strName.size() , man.strName.capacity() );<br><br>		man.strAddress = &quot;abcdef&quot;; <br>		man.strName = &quot;abc&quot;; <br>		Sleep( 1000 ); //这里sleep是为了让大家有时间在任务管理器中看到内存增长的过程，不至于一下子耗尽内存. <br>	} <br><br><br>	return 0; <br>}<br><br><br>我选取我这里的一个循环中的输出，如下:<br><br><br>before memset:  char buffer address( heap address ) to store string = 00636200 ,<br> size = 0 , capacity = 15<br>after memset:  char buffer address( heap address ) to store string = 00000000 ,<br>size = 0 , capacity = 0<br><br>下面把上述代码进行简化便于分析:<br><br>	while( true ) <br>	{ <br>		MAN man; 			//这里会使用man由编译器自动生成缺省构造函数来调用strName的缺省构造函数对strName进行构造.<br>		<br>		memset( &amp;man , 0 , sizeof( MAN ) );<br>		上面的memset操作会把 &amp;man 这个地址开始的 sizeof( MAN )字节的内存空间全部清零.<br>		这也就意味着 man 对象内部的每个成员子对象所占据的内存都被清零.<br>		man 对象内部一个 std::string , 而std::string 内部包含一个std::string用于实际存储字符串的指向动态分配的堆内存的指针，<br>		我们假设这个指针的名称为 m_pCharBuffer;<br>		在std::string的析构函数中释放这个动态分配的堆内存的时候需要使用这个m_pCharBuffer，也即是调用 delete[] m_pCharBuffer;<br>		如果我写出下在的代码:<br>		char *m_pCharBuffer = new char[ BUFFER_SIZE ];	这一个操作即是strName的缺少构造函数的操作，只不过 BUFFER_SIZE = 15 + 1(最后有一个'\0');<br>		m_pCharBuffer = NULL;	//这一个操作与上述的 memset 对 man.strName中用于指向动态内存的指针所产生的作用相同:将指针所指向的堆内存地址清零.<br>		delete[] m_pCharBuffer;	//此时 m_pCharBuffer 为NULL ， 不过在C++中， delete NULL指针是安全的.不过因为 m_pCharBuffer 已经不指向上述new出来的内存<br>								//所以这里进行 delete[] m_pCharBuffer 时已经不能进行资源的释放了，也即是发生了内存泄漏.<br><br>		man.strName = &quot;abc&quot;; <br>		上面的赋值操作中，实际上要调用: std::string::operator=( const char* );<br>		首先，operator=会判断当前的strName的 capacity能否容纳下&quot;abc&quot;，由上面的memset之后我们可以看出此时存储 capacity 值的变量因为memset为0，所以<br>		man.strName.capacity() 输出为0，这也就意味着这个&quot;容积&quot;不能容纳下3个字节的&quot;abc&quot;.<br>		<br>		所以这时 operator= 要扩大内部用于存储字符串的缓冲区,扩充的基本原理如下:(代码进行简化处理)<br>		<br>		std::string&amp; operator=( const char *szString )<br>		{<br>			// check parameter<br>			<br>			if( m_pCharBuffer != szString )	// 防止 self-assign<br>			{<br>				delete[] m_pCharBuffer;<br>				m_pCharBuffer = new char[ NEW_SIZE ];<br>				memcpy( m_pCharBuffer , szString , strlen( szString ) + 1 );<br>			}<br>			<br>			return *this;<br>		<br>		}<br>		<br>		上面的操作: *reinterpret_cast&lt; const int* &gt;( man.strName.c_str() ) 即是相当于获取这个 m_pCharBuffer 的地址.<br>		这一点你一定要明白.<br>		<br>		由上面的代码以及运行输出可以知道,<br>		注意: 在调用 strName = &quot;abc&quot;时，已经进行了memset操作，此时的 m_pCharBuffer 已经因为上面的 memset操作而被清零，即是 m_pCharBuffer = NULL,<br>		因为memset操作不会调用析构函数 ，所以实际上在清零之前它所指向的动态内存块并没有被释放，<br>		在 operator=中，delete[] m_pCharBuffer; 相当于 delete[] NULL;<br>		这就不能释放 m_pCharBuffer 之前在缺省构造时所指向的动态分配的 15 + 1 字节的内存了，所以出现了内存泄漏.<br>		<br>	}<img src ="http://www.cppblog.com/findingworld/aggbug/109077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">luckycat</a> 2010-03-06 22:50 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109077#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109075</link><dc:creator>小苏</dc:creator><author>小苏</author><pubDate>Sat, 06 Mar 2010 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109075</guid><description><![CDATA[@luckycat<br><br>能否解释一下，为什么内存使用会不停增长呢？<img src ="http://www.cppblog.com/findingworld/aggbug/109075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">小苏</a> 2010-03-06 22:10 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109075#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109073</link><dc:creator>luckycat</dc:creator><author>luckycat</author><pubDate>Sat, 06 Mar 2010 13:35:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109073</guid><description><![CDATA[@小苏<br>你运行后仔细观察这个编译后运行的exe在&quot;windows任务管理器&quot;中对应的<br>&quot;内存使用&quot;数值.<br>我用VC2005和VC2008都测试过，结果是&quot;内存不停增长&quot;.<br><br>还用哪位同学运行过我上面的测试代码，出来公布一下测试结果，谢谢!<img src ="http://www.cppblog.com/findingworld/aggbug/109073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">luckycat</a> 2010-03-06 21:35 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109073#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109071</link><dc:creator>小苏</dc:creator><author>小苏</author><pubDate>Sat, 06 Mar 2010 13:29:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109071</guid><description><![CDATA[@luckycat<br><br>这段测试代码我跑了二十分钟，内存也没见增长啊~~~<br>各位大侠都看出来啦，我很少用C++写程序~~~~<img src ="http://www.cppblog.com/findingworld/aggbug/109071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">小苏</a> 2010-03-06 21:29 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109071#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109068</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 06 Mar 2010 13:25:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109068</guid><description><![CDATA[@luckycat<br>我在想他用list估计是因为别的语言都叫list，不知道C++叫的是vector……<img src ="http://www.cppblog.com/findingworld/aggbug/109068.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">陈梓瀚(vczh)</a> 2010-03-06 21:25 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109068#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: C++基础知识: list结构体排序方法(一)</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109066</link><dc:creator>luckycat</dc:creator><author>luckycat</author><pubDate>Sat, 06 Mar 2010 13:01:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109066</guid><description><![CDATA[@小苏<br>你后续修改的代码，在我看来，即使在多个编译器下都是OK的，但是就代码风格来说，还有改进的地方.<br>在编码过程中，我很少会对struct进行memset操作，只是偶尔会对sockaddr进行memset操作;更不会对class进行memset操作.<br><br>在你上述的代码中，你对MAN进行memset操作，无非也就是想将各个成员的初值清零，如果基于这个出发点，那设计一个构造函数多好:<br>structMan::structMan( UINT32 enumSexType = SEXY_TYPE_MAN , \<br>					UINT16 uiAge = 0 , \<br>					const std::string &amp;refStrName = &quot;&quot; , \<br>					const std::string &amp;refStrAddress = &quot;&quot; )<br>:sexType( enumSexType ) , usAge( uiAge ) , \<br>strName( refStrName ) , strAddress( refStrAddress )<br>{<br>    // check parameters here。<br>}<br><br>只需要少量的代码就会带来大量的方便，而且你也就再也不用memset.<br>你也就不需要对struct的各个成员依次赋值了，直接传参构造就可以了，这样代码应该会更优雅一些.<br><br>另一方面，对 std::list 进行sort操作从逻辑上是没有问题的，但是设计风格上是有问题的:<br>因为std::list中的每一个成员是基于链的形式连接在一起的，所以我们不能对其进行随机访问，<br>如果我们要访问std::list中的第N个成员，那么我们需要从链表头开始向链表尾部依次迭代N次,<br>在这种情况下，如果一个链表过大，那么这里就有效率问题.<br><br>一般情况下，我们只对&quot;类似于数组的可以随机访问&quot;的std容器进行排序.<br><br><img src ="http://www.cppblog.com/findingworld/aggbug/109066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">luckycat</a> 2010-03-06 21:01 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/109050.html#109066#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>re: ILOVEQQ木马及源码下载[未登录]</title><link>http://www.cppblog.com/findingworld/archive/2010/03/06/18201.html#109064</link><dc:creator>baggio</dc:creator><author>baggio</author><pubDate>Sat, 06 Mar 2010 12:35:00 GMT</pubDate><guid>http://www.cppblog.com/findingworld/archive/2010/03/06/18201.html#109064</guid><description><![CDATA[支持一下，目前想研究一下木马源码，顶一下<img src ="http://www.cppblog.com/findingworld/aggbug/109064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/findingworld/" target="_blank">baggio</a> 2010-03-06 20:35 <a href="http://www.cppblog.com/findingworld/archive/2010/03/06/18201.html#109064#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>