C++中内存泄漏的检查与定位
2012-07-17 17:51
405 查看
本文仅仅是一些简短讲述一下,关于C++在Windows平台下内存泄漏内存泄漏的检查与定位。请参阅《最快速度找到内存泄漏》。
在Windows平台下,可以借助头文件<crtdbg.h>中定义的一以下几个函数来完成。
以下是_CrtDumpMemoryLeaks()的详细代码。(仅在Debug版本下有效)
这样在当前程序执行结束后,在Vistual Studio的Output窗口中会输出如下信息:
Detected memory leaks!
Dumping objects ->
c:/work/test.cpp(186) : {52} normal block at 0x003C4410, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
以上信息似乎仅仅告诉了我们内存泄漏发生了,但依旧难以定为具体的内存泄漏的位置。
以下是改进后的版本:
但有些时候,这依旧很难帮助我们找到具体的内存泄漏点。
我们注意到,在以上内存泄漏报告中有一个奇怪的信息({52}),其表示是第52次内存分配时,所分配的内存未被回收。
方法long _CrtSetBreakAlloc(long lBreakAlloc)可以使程序停止在指定的内存分配操作处(即:第52次内存分配)。
再次在VS中执行上述代码,程序会在指定处停止并进入调试状态。通过查看函数调用堆栈,便可以精确定位出错的代码行,及当时的程序运行状态。
在这里,还有一点要注意的是C++的全局变量,一些全局变量的初始化会在进入main方法前就发生了。这种情况下,上述方法依旧无效。详见下例:
上述代码中,g_MyCls对象实例的初始化在进入main方法前就完成了。在这种情况下,可以通过设置条件断点来完成。具体如下:
在以下行处设置条件断点,在变量lRequest等于给定内存分配次数时停止执行。
上述方法在本人的机器(Windows 7 VS2010)上测试有效,暂时未在其它情况下验证过。
在Windows平台下,可以借助头文件<crtdbg.h>中定义的一以下几个函数来完成。
_CrtDumpMemoryLeaks(); // 置于main函数最后,打印内存泄露报告 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); // 置于main函数开头(当当前程序没有统一退出点时) long _CrtSetBreakAlloc(long lBreakAlloc); //用于在给定内存分配操作时停止当前程序
以下是_CrtDumpMemoryLeaks()的详细代码。(仅在Debug版本下有效)
#include <crtdbg.h> void main() { int* pLeak = new int[10]; pLeak = nullptr; _CrtDumpMemoryLeaks(); }
这样在当前程序执行结束后,在Vistual Studio的Output窗口中会输出如下信息:
Detected memory leaks!
Dumping objects ->
c:/work/test.cpp(186) : {52} normal block at 0x003C4410, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
以上信息似乎仅仅告诉了我们内存泄漏发生了,但依旧难以定为具体的内存泄漏的位置。
以下是改进后的版本:
#define _CRTDBG_MAP_ALLOC // 用于将malloc和free函数重定向至DEBUG版本,使之能输出对应的源文件及行号。 #include <crtdbg.h> #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif // 重定向new关键字,否则对于所有的new操作,依旧无法正确输出对应的源文件及行号。 void main() { int* pLeak = new int[10]; pLeak = nullptr; _CrtDumpMemoryLeaks(); }
但有些时候,这依旧很难帮助我们找到具体的内存泄漏点。
我们注意到,在以上内存泄漏报告中有一个奇怪的信息({52}),其表示是第52次内存分配时,所分配的内存未被回收。
方法long _CrtSetBreakAlloc(long lBreakAlloc)可以使程序停止在指定的内存分配操作处(即:第52次内存分配)。
#include <crtdbg.h> void main() { _CrtSetBreakAlloc(52); int* pLeak = new int[10]; pLeak = nullptr; _CrtDumpMemoryLeaks(); }
再次在VS中执行上述代码,程序会在指定处停止并进入调试状态。通过查看函数调用堆栈,便可以精确定位出错的代码行,及当时的程序运行状态。
在这里,还有一点要注意的是C++的全局变量,一些全局变量的初始化会在进入main方法前就发生了。这种情况下,上述方法依旧无效。详见下例:
struct MyCls { string SubExprStr; }; MyCls g_MyCls = { string("Hello world!") };
上述代码中,g_MyCls对象实例的初始化在进入main方法前就完成了。在这种情况下,可以通过设置条件断点来完成。具体如下:
// file 'dbgheap.c' extern "C" static void * __cdecl _heap_alloc_dbg_impl( size_t nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp ) { // ... /* lock the heap */ _mlock(_HEAP_LOCK); __try { // ... /* break into debugger at specific memory allocation */ if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc) _CrtDbgBreak();
在以下行处设置条件断点,在变量lRequest等于给定内存分配次数时停止执行。
if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)
上述方法在本人的机器(Windows 7 VS2010)上测试有效,暂时未在其它情况下验证过。
相关文章推荐
- 如何检查C++中的内存泄漏
- Windows平台上C++开发内存泄漏检查方法
- C/C++内存泄漏检查之经验
- 如何检查C++中的内存泄漏
- 检查 C++ 内存泄漏(待整理)
- 加入代码以检查C++中的内存泄漏
- Windows平台上C++开发内存泄漏检查方法
- C++内存泄漏检查心得
- c++ 内存泄漏检查
- 如何检查C++中的内存泄漏
- c/c++中内存泄漏的检查与避免
- C/C++内存管理之内存泄漏检查
- 【转】C++内存泄漏检查心得
- C++内存泄漏检查心得
- 如何检查C++中的内存泄漏
- C++内存泄漏检查心得
- 如何检查C++中的内存泄漏
- 如何检查C++中的内存泄漏 vs自带
- C++内存泄漏检查心得
- valgrind检查C/C++内存泄漏