内存漏洞的检查也许你已经知道,在C++和C语言中指针问题也就是内存申请与释放是一个令人头疼的事情,假如你申请了内存,但没有释放,并且你的程序需要长时间地运行,那么,系统的资源将逐渐减少,当系统的资源全部被用完时,系统将会崩溃。所以在开发程序的过程中一定要保证资源的完全释放。下面我们来介绍内存漏洞的检查。
也许你会问,系统是怎样支持内存漏洞的检查的?其实在你的Debug版本中所有的有关内存分配的函数都是被重载过的,具体过程是这样的,当你的程序申请内存时,它首先调用一般的内存分配函数分配一块稍大的内存块。在这一内存块中分为四个小块:Heap Information, buffer , User memory block, buffer。第一块为有关堆的信息,比如,申请该内存的地点(文件名,行号),此内存块的类型(如整型,浮点,或某一类的对象)等等。第二块是一个缓冲区,用于截获用户对其申请内存使用越界的情况。第三块是真正给用户的内存,返回的指针也是指向这儿。第四块也是一个缓冲区,作用同第二块。
当你申请的内存均被记录在案后,要检查内存漏洞就比较容易了,粗略地说,假如你要检查某一程序段是否有内存漏洞,你只需在这一程序 段的开始要求系统为你做一个内存使用情况的映象,记录下程序开始时的内存使用情况,然后在程序段的末尾再使系统为你做一次内存映象,比较两次映象,以检查是否有没释放的内存,假如有未释放的内存,根据这一块中有关分配情况的信息来告诉用户在那儿申请的内存没释放。
具体地讲检查内存漏洞需要以下几个步骤:
l 在你所检测的程序段的开始处建立一个CmemoryState对象,调用其成员函数Checkpoint,以取得当前内存使用情况的快照;
l 在你所检测的程序段的末尾处再建立一个CmemoryState 对象,调用其成员函数Checkpoint ,以取得当前内存使用情况的快照;
l 再建立第三个CmemoryState 对象,调用其成员函数Difference,把第一个CmemoryState对象和第二个CmemeoryState对象作为其参数.,如果两次内存快照不相同,则该函数返回非零,说明此程序 段中有内存漏洞。下面我们来看一个典型的例子:// Declare the variables needed
#ifdef _DEBUG
     CMemoryState oldMemState, newMemState, diffMemState;
     OldMemState.Checkpoint();
#endif
    // do your memory allocations and deallocations...
     CString s = "This is a frame variable";
     // the next object is a heap object
     CPerson* p = new CPerson( "Smith", "Alan", "581_0215" );
#ifdef _DEBUG
     newMemState.Checkpoint();
     if( diffMemState.Difference( oldMemState, newMemState ) )
     {
        TRACE( "Memory leaked!\n" );
}
#endif

解决方案 »

  1.   

    这种问题只能仔细检查代码,问是问不出来的.如果没有内存泄露,那么应该是其他资源没有释放.
    另外,delete指针之后,立即将其赋NULL,否则以后检查指针有效性时会误判.
      

  2.   

    用Rational Purify工具,它可以告诉你有没有内存泄漏等运行期错误。
      

  3.   

    我的经验是:
    访问任何共享资源,一定要使用互斥方法。如Critical_Section等。arloan(泡泡)说的:delete后立即赋NULL是好习惯,但不是有效的保证。
      

  4.   

    多谢诸位的关注!
    1。在程序运行时,我打开任务管理器,发现CPU利用率和内存使用,
    没有发现异常。
    2。在释放指针时,我也立即将其赋值为NULL了。
    3。我的程序中也没有调用系统的其它资源(GDI,定时器。)。另外,我的一点进步就是:现在50个线程基本可以稳定运行了,但是80(×2)
    个线程还是不行,还是要崩溃。
    而在两台机器上测试时,程序更容易崩溃。一点经验给大家共享:
    大家在删除对象指针时都知道使用delete []p;
    请大家在删除字符串时,也尽量使用该语法,尽管在大多数情况下,
    把那个不起眼的中括号去掉没有什么问题,但是这也是一个好的习惯。
    我的程序经过这么一改,觉得稳定性加强了,本来50个线程很不能稳定运行,
    而现在基本可以稳定运行了。
      

  5.   

    你好,我想看看它的原代码,请发给我吧[email protected]
      

  6.   

    很抱歉,是删除对象指针数组时,使用delete []p;
      

  7.   

    Windows对套接字的数目是有限制的!
    是不是你用了过多的socket?!
      

  8.   

    不是,因为是在程序运行中崩溃,即是说,200个socket已经创建,
    并已经成功地接收和发送了一些数据。
    另外,200个socket对于Windows也不算多的。:)
      

  9.   

    你试试bound checker,这是我们公司windows下的检查资源泄漏的标准程序。
    另外,true coverage做单元测试。肯定是你代码的问题了,跑50个线程根本
    就不算多了。
      

  10.   

    我的程序的调用关系实际也较简单,我觉得没有什么内存问题(:P)
    不过不知道哪儿可以down那个bound checker?我用它再查一查看吧!
      

  11.   

    sorry, perhaps you have misunderstood me,
    I mean delete, cooresponding to new, in sample code:
    char *p = new char[10];
    .....//use p
    delete []p; // i mean use this line instead of delete p;
      

  12.   

    能发一份你的代码给我吗...
    我也在做c/s的东西,
    也许开辟很多线程[email protected]
      

  13.   

    感谢大家的热情参与!
    大家都提到BoundsChecker,可是我还是不知道哪儿有啊?
    谁能帮帮我啊?给我发一个,或者告诉我哪儿去当啊!
    我的电子邮件地址是:[email protected]