使用Visual Leak Detector for Visual C++ 捕捉内存泄露
什么是内存泄漏?
内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
C和C++内存泄露
对于C和C++这种没有Garbage Collection 的语言来讲,我们主要关注两种类型的内存泄漏:
堆内存泄漏(Heap leak)。对内存指的是程序运行中根据需要通过malloc,realloc, new等从堆中分配的一块内存,完成后必须通过调用对应的 free或者delete 释放掉。如果程序设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak.
系统资源泄露(Resource Leak)。主要指程序使用系统分配的资源比如 Bitmap,Handle,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。
如何解决内存泄露?
内存泄露的问题其困难在于:
1、编译器不能发现这些问题。
2、运行时才能捕获到这些错误,这些错误没有明显的症状,时隐时现。
3、对于手机等终端开发用户来说,尤为困难。
下面从三个方面来解决内存泄露:
第一,良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露。当程序稳定之后,再来检测内存泄露时,无疑增加了排除的难度和复杂度。
使用了内存分配的函数,要记得要使用其释放函数释放掉。
Heap memory:
malloc\realloc ------ free
new \new[] ---------- delete \delete[]
GlobalAlloc------------GlobalFree
Resource Leak :
对于系统资源使用之前要仔细看其使用说明,防止错误使用或者忘记释放掉系统资源。
对于基于引用计数的系统对象尤其要注意,因为只有其引用计数为0时,该对象才能正确被删除。而其使用过程中又生成的新的系统资源,使用完毕后,如果没有及时删除,都会影响其引用计数。
使用Visual Leak Detector for Visual C++
简介
Visual Leak Detector是一款免费的、健全的、开源的Visual C++内存泄露检测系统。相比Visual C++自带的内存检测机制,Visual Leak Detector可以显示导致内存泄露的完整内存分配调用堆栈。
使用方法
VLD简单易用,文档也很丰富,对于内存泄露的具体位置也能以调用堆栈的形式详细的显示出来。
下载安装后,仅仅需要告诉Visual C++在哪里找到include文件和lib文件。
C/C++ -> General -> Additional Include Directories = C:\Program Files (x86)\Visual Leak Detector\include
Linker -> General -> Additional Library Directories = C:\Program Files (x86)\Visual Leak Detector\lib\Win32
Linker -> Input-> Additional Dependencies = vld.lib
然后,在代码上的变动就只需要简单的加上#include <vld.h> 就可以了。
当你在Visual C++中调试运行你的程序时,在程序结束后VLD将在output窗口输出一个内存泄露报告,该报告包括了你的程序中内存分配的完成调用栈信息。双击调用栈的某一行,就可以迅速跳转到你的代码编辑器相应的位置。
Visual Leak Detector有一些配置项,可以设置内存泄露报告的保存地(文件、调试器),拷贝"\Visual Leak Detector"路径下的vld.ini文件到工程的Debug目录下(在IDE运行的话,则需要拷贝到工程目录下),修改以下项:
ReportFile = .\memory_leak_report.txt
ReportTo = both
可以看到在Debug目录下生成文件memory_leak_report.txt,跟VS中Output窗口输出的内容一样。
总之,VLD是一种高效的诊断、修复C/C++程序内存泄露的方法。
应用举例
#include "stdafx.h" #ifdef _DEBUG //在Release模式下,不会链接Visual Leak Detector #include "vld.h" #endif int _tmain(int argc, _TCHAR* argv[]) { char* ch1 = new char[100]; char* ch2 = (char*)malloc(200); /* if (ch1 != NULL) { delete[] ch1; ch1 = NULL; } if (ch2 != NULL) { free(ch2); ch1 = NULL; } */ return 0; }
Output输出:
Visual Leak Detector Version 2.2.3 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 1 at 0x008CD6F8: 100 bytes ----------
Call Stack:
c:\users \consoleapplication\consoleapplication.cpp (12): ConsoleApplication.exe!wmain + 0x7 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (533): ConsoleApplication.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): ConsoleApplication.exe!wmainCRTStartup
0x74EE8543 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x770EAC69 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes
0x770EAC3C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes
Data:
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD ........ ........
---------- Block 2 at 0x008CD798: 200 bytes ----------
Call Stack:
c:\users\ \consoleapplication\consoleapplication.cpp (13): ConsoleApplication.exe!wmain + 0xD bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (533): ConsoleApplication.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): ConsoleApplication.exe!wmainCRTStartup
0x74EE8543 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x770EAC69 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes
0x770EAC3C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes
Data:
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD ........ ........
Visual Leak Detector detected 2 memory leaks (372 bytes).
Largest number used: 372 bytes.
Total allocations: 372 bytes.
Visual Leak Detector is now exiting.
The program '[0x262C] ConsoleApplication1.exe' has exited with code 0 (0x0).
输出的部分主要分为两块
Call Stack部分:
是泄露内存的调用堆栈,其中显示了泄露资源创建的位置,双击便可以定位到相应的代码部分。
Data部分:
即泄露部分的内存内容。