使用 CRT 库查找内存泄漏
发布于 2022-01-19
编写 C/C++ 程序需要关注代码逻辑是否存在内存泄漏。Visual Stdio C++ 的 CRT 库自带了检测内存泄漏的工具。
首先在程序的开头按照以下的顺序包含以下代码:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define _CRTDBG_MAP_ALLOC
这行代码会把 CRT 里面分配和释放内存相关的函数映射转成成对于的调试版。例如 malloc
映射转成 _malloc_dbg
,free
映射转成 _free_dbg
。调试版函数除了分配和释放内存,还做一些记录的相关工作。
然后在程序退出是调用 _CrtDumpMemoryLeaks()
,这样就会输出检测内存泄漏的结果。下面是个完整的例子:
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(sizeof(int) * 100);
_CrtDumpMemoryLeaks();
}
输出结果:
Detected memory leaks!
Dumping objects ->
ConsoleApplication25.cpp(9) : {88} normal block at 0x007F4BF0, 400 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
#include <stdlib.h>
#include <crtdbg.h>
否则的话,则无法检测到泄漏内存的具体源文件和行数。
另外,一般复杂的程序有多个程序退出口,有时候我们无法找到一个合适的地方调用 _CrtDumpMemoryLeaks()
。因此还有另外一种写法:
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#include "aaa.h"
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
int *arr = (int *)malloc(sizeof(int) * 100);
}
即在程序的开头加上:
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
程序结束后会自动输出检测内存泄漏的结果。
C++ 分配和释放内存使用的是 new 和 delete。我们还需要做一些工作:
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#include <string>
#define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__)
#define new DEBUG_NEW
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
int *arr = (int *)malloc(sizeof(int) * 100);
std::string* s1 = new std::string("123456789");
}
输出结果:
Detected memory leaks!
Dumping objects ->
{167} normal block at 0x014E7068, 8 bytes long.
Data: <` M > 60 C0 4D 01 00 00 00 00
ConsoleApplication25.cpp(17) : {166} normal block at 0x014DC060, 28 bytes long.
Data: <hpN 123456789 > 68 70 4E 01 31 32 33 34 35 36 37 38 39 00 CD CD
ConsoleApplication25.cpp(15) : {165} normal block at 0x014E7B88, 400 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.