首页 > 代码库 > [VS] 使用Visual Studio查找和定位内存泄露 @Windows

[VS] 使用Visual Studio查找和定位内存泄露 @Windows

一,代码示例

 1 #include <stdio.h> 2  3 void* memleak1(); 4 void* memleak2(); 5  6 int main() 7 { 8     void *p1 = memleak1(); 9     void *p2 = memleak2();10 11     printf("p1=%p, p2=%p\n", p1, p2);12 13     return 0;14 }
main.c
1 /* memleak1.c */2 #include <stdlib.h>3 4 void* memleak1()5 {6     return malloc(1);7 }
memleak1.c
1 /* memleak2.c */2 #include <stdlib.h>3 4 void* memleak2()5 {6     return malloc(2);7 }
memleak2.c

二、如何查找是否有内存泄露

第一步:把下面的代码黏贴到main()函数所在的源文件:

#ifdef _DEBUG #include <stdlib.h>#include <crtdbg.h> #ifndef DEBUG_NEW#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)#define new DEBUG_NEW#endif #endif

第二步,把下面的代码黏贴到main()函数的开头:

char *b;_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);b = (char*) malloc(20);

最后,重新编译debug模式并运行vs工程,在输出窗口就可以看到这样的提示:

Detected memory leaks!Dumping objects ->{56} normal block at 0x00171580, 20 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {55} normal block at 0x00171540, 2 bytes long. Data: <  > CD CD {54} normal block at 0x00171500, 1 bytes long. Data: < > CD Object dump complete.

这里,我们就可以看到内存泄露的位置和泄露的数量。

三、如何定位内存泄露的位置

第一步,添加预定义宏(preprocessor marco)到vs工程中:

_CRTDBG_MAP_ALLOC=1

这时候重新编译并运行工程,我们会得到这样的输出,说明我们已经定位20个byte的泄露来自于main.c里的第25行,正是我们加入的测试内存泄露的代码。但是我们还是没有定位到另外两处内存泄露。

Detected memory leaks!Dumping objects ->c:\users\jxion\documents\github\memleak\memleak\main.c(25) : {56} normal block at 0x00401580, 20 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {55} normal block at 0x00401540, 2 bytes long. Data: <  > CD CD {54} normal block at 0x00401500, 1 bytes long. Data: < > CD Object dump complete.

第二步,在所有我们怀疑有内存泄露的源文件的开始位置,添加下面的代码:

#ifdef _DEBUG #include <stdlib.h>#include <crtdbg.h> #ifndef DEBUG_NEW#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)#define new DEBUG_NEW#endif #endif

这时我们可以定位所有的内存泄露的位置了:

Detected memory leaks!Dumping objects ->c:\users\jxion\documents\github\memleak\memleak\main.c(25) : {56} normal block at 0x000F1580, 20 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD c:\users\jxion\documents\github\memleak\memleak\memleak2.c(19) : {55} normal block at 0x000F1540, 2 bytes long. Data: <  > CD CD c:\users\jxion\documents\github\memleak\memleak\memleak1.c(19) : {54} normal block at 0x000F1500, 1 bytes long. Data: < > CD Object dump complete.

四、查找第三方库是否有内存泄露:

调用第三方预编译库(prebuilt)也有可能有内存泄露,但是我们没办法把上面的代码加入到第三方库中重新编译库。我们只能使用间接的方法。例如:打印我们认为可能有内存泄露的第三方函数调用,然后与输出窗口里的内存泄露地址做比较,如上面的例子中,内存泄露位置为:

Detected memory leaks!Dumping objects ->c:\users\jxion\documents\github\memleak\memleak\main.c(25) : {56} normal block at 0x002D1580, 20 bytes long. Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD {55} normal block at 0x002D1540, 2 bytes long. Data: <  > CD CD {54} normal block at 0x002D1500, 1 bytes long. Data: < > CD Object dump complete.

同时打印的内存分配地址为:

发现了没?两者的地址是一致的,我们同样可以拿这个作为一个定位内存泄露的原则。

 

[VS] 使用Visual Studio查找和定位内存泄露 @Windows