[DEBUG阶段][源码] Visual Studio 下C++内存泄露检测

刺骨的言语ヽ痛彻心扉 2022-04-11 06:09 159阅读 0赞

转自
[url]http://www.cnblogs.com/zouzf/p/4152279.html\[/url\]

相关文章
[url]http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html\[/url\]
[url]http://blog.csdn.net/KangRoger/article/details/39317503\[/url\]

参考文章:
[url]http://msdn.microsoft.com/zh-cn/library/x98tx3cf.aspx\[/url\]
[url]http://www.cnblogs.com/jianqiang2010/archive/2010/12/02/1894327.html\[/url\]
[url]http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html\[/url\]

1、在main方法所在的文件里加上如下代码:

  1. //可以定位到发生内存泄露 所在的文件和具体那一行,用于检测 malloc 分配的内存
  2. #define _CRTDBG_MAP_ALLOC
  3. #include <stdlib.h>
  4. #include <crtdbg.h>
  5. //把分配内存的信息保存下来,可以定位到那一行发生了内存泄露。用于检测 new 分配的内存
  6. #ifdef _DEBUG
  7. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
  8. #endif
  9. //有用
  10. inline void EnableMemLeakCheck()
  11. {
  12. //该语句在程序退出时自动调用 _CrtDumpMemoryLeaks(),用于多个退出出口的情况.
  13. //如果只有一个退出位置,可以在程序退出之前调用 _CrtDumpMemoryLeaks()
  14. _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
  15. }

2、在main方法里开始的地方调用 EnableMemLeakCheck() 方法。到此为止,可以检测的内存泄露的信息里,有一部分是可以定位到具体的文件以及所在的行的,但还是有一些其他工程或者其他文件里如果发生内存泄露还是没有定位到具体的文件和行,这些信息会在vs的输出窗口里看到。如下面的输出,第一处泄露有很具体的定位信息,第二处的泄露却没有。

[quote]
q:\project_wydxml\wydxmlcreator\project_win32\wydxmlcreator.cpp(52) : {256} normal block at 0x00ABBC40, 200 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{254} normal block at 0x00ABF6F8, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
[/quote]

3、对于那些没有定位出具体位置的内存泄露处理如下:记录下该处内存是第几次分配的,比如上面的第三行和第四行表示第二处内存泄露,第三行里 {}里的254表示该处泄露的内存是第 254 次分配的。结束运行,在 EnableMemLeakCheck() 方法 后加上一句代码: _CrtSetBreakAlloc(254); 括号里的参数就是没有得到准确定位的泄露内存的被分配的序数,其他的就别改了,再次运行,程序就会在 分配 第 254 块 内存时进入断点,通过断点堆栈就可以比较方便的知道哪些泄露了。

4、注意事项:对于 new 出来的一些自定义类的对象,直接调用其析构方法时,EnableMemLeakCheck 还是会将其视作没有释放内存的,要直接调用 delete xxx 才行。。。如: A *a = new A(); a->~A(); 会被判做有问题的, delete a 才视作没问题。。。。

5、令外,还有个监控某片代码段是否有内存泄露的,如下。如果有这段代码有泄露,_CrtMemDifference就会比较出来,然后 _CrtMemDumpStatistics输出相关信息。输出的信息没有具体的定位到具体文件具体哪一行,但有时还是有些辅助作用的吧

  1. _CrtMemState s1, s2, s3;
  2. _CrtMemCheckpoint( &s1 );
  3. //your code
  4. CrtMemCheckpoint( &s2 );
  5. if ( _CrtMemDifference( &s3, &s1, &s2) )
  6. _CrtMemDumpStatistics( &s3 );

全部代码如下:

  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include "wydxml.h"
  4. //可以定位到发生内存泄露 所在的文件和具体那一行,用于检测 malloc 分配的内存
  5. #define _CRTDBG_MAP_ALLOC
  6. #include <stdlib.h>
  7. #include <crtdbg.h>
  8. //把分配内存的信息保存下来,可以定位到那一行发生了内存泄露。用于检测 new 分配的内存
  9. #ifdef _DEBUG
  10. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
  11. #endif
  12. //有用
  13. inline void EnableMemLeakCheck()
  14. {
  15. //该语句在程序退出时自动调用 _CrtDumpMemoryLeaks(),用于多个退出出口的情况.
  16. //如果只有一个退出位置,可以在程序退出之前调用 _CrtDumpMemoryLeaks()
  17. _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
  18. }
  19. int _tmain(int argc, _TCHAR* argv[])
  20. {
  21. EnableMemLeakCheck();
  22. //运行到 第 191 次 内存分配的时候停下来
  23. //_CrtSetBreakAlloc(191);
  24. char* p = new char[100];
  25. char* p1 = new char[200];
  26. char* p2 = (char*)malloc(600);
  27. delete p;
  28. getchar();
  29. //_CrtDumpMemoryLeaks();//这个代码好像会输出额外多余的内存分配信息
  30. return 0;
  31. }

以下转自
[url]http://www.cnblogs.com/huhuuu/p/3576710.html\[/url\]

C++没有java的内存垃圾回收机制,在程序短的时候可能比较容易发现问题,在程序长的时候是否有什么检测的方法呢?

  假设有一个函数可以某点检测程序的内存使用情况,那是否可以在程序开始的时候设置一个点,在程序结束的时候再设置一个点,比较这两个值是否一样就可以知道内存泄露的情况了。

  windows下的内存检测方法:

  1. #define _CRTDBG_MAP_ALLOC //一定要加上这一句
  2. #include <stdlib.h>
  3. #include <crtdbg.h>
  4. #include <iostream>
  5. using namespace std;
  6. _CrtMemState s1, s2, s3;
  7. void GetMemory(char *p, int num)
  8. {
  9. p = (char*)malloc(sizeof(char) * num);
  10. }
  11. int main(int argc,char** argv)
  12. {
  13. _CrtMemCheckpoint( &s1 ); //检测当前内存的使用情况
  14. char *str = NULL;
  15. int n=1000;
  16. GetMemory(str, 100);//这里申请后没有释放内存,内存泄露了
  17. _CrtMemCheckpoint( &s2 );
  18. _CrtMemDifference( &s3, &s1, &s2); //比较s1,s2的内存差异,结果放s3
  19. printf("%ud",s3.lTotalCount);
  20. return 0;
  21. }

[color=red][b]之前一直没有搞清楚_CrtDumpMemoryLeaks();的调用方法,因为之前执行程序都是ctrl + F5的,原来发现这个函数是在F5的时候生效[/b][/color]

  1. #ifdef _DEBUG
  2. #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
  3. #else
  4. #define DEBUG_CLIENTBLOCK
  5. #endif
  6. #define _CRTDBG_MAP_ALLOC
  7. #include <crtdbg.h>
  8. #ifdef _DEBUG
  9. #define new DEBUG_CLIENTBLOCK
  10. #endif
  11. int main()
  12. {
  13. int* p = new int();
  14. int n=5;
  15. while(n--){
  16. new int;
  17. }
  18. _CrtDumpMemoryLeaks();
  19. return 0;
  20. }

[align=center][img]http://images.cnitblog.com/i/273314/201403/162016182302448.png\[/img\]\[/align\]

嗯,编译器提示有6个内存块内存泄露了。

同时,注意其中也显示了内存泄露的行号,利于调试。

在linux下也有类似的方法

参考:http://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html

发表评论

表情:
评论列表 (有 0 条评论,159人围观)

还没有评论,来说两句吧...

相关阅读