最近将一个指纹匹配算法按照AFIS系统的接口标准做成dll上服务器测试,结果在进行200万人指纹的大库比对时出错了,通过分析发现是dll中存在内存泄露导致系统资源耗尽。虽然一次只有那么200kByte,但乘上200万这个基数也是不小。于是找来了两个工具来检测代码中的内存泄露:VLD和LeakDiag。
1.Visual Leak Detector 1.0 (VLD)
这是一个小巧内存检测工具,是为Visual C++用户设计的。其特色为:
简单易用,只需要在需要进行内存泄漏检测的的主程序代码中加入#include "VLD.h“,并将编译好的Lib文件放入默认的库目录,然后在Visual C++用Debug模式编译运行程序,程序运行结束后便可在Visual C++的输出窗口看到内存泄露检测结果。
通过宏定义控制测试行为,如报告的详略等。
支持Windows X64。
检测报告很直观,甚至能显示泄漏内存的内容。
下面是一段用于演示VLD功能的代码:
TestVLD.cpp
#include "stdafx.h"
#include "vld.h"
#include "afx.h"
#include "string.h"
typedef void(*FARPROC2)(int, char*); // 用于调用dll中函数的指针
void leak5Bytes(); // 泄漏5个字节内容为"ABCDE"内存
void leakInDll(); // 调用dll中会造成内存泄漏函数
int _tmain(int argc, _TCHAR* argv[])
{
int * p = new int[10];
for (int i=0; i<10; ++i) p[i]=i; // 泄漏10个int的内存,内容分别为0到9
leak5Bytes(); // 泄漏5个字节内存
leakInDll(); // 调用dll中会造成内存泄泄漏的函数
return 0;
}
void leak5Bytes()
{
char * p = new char[5];
for (int i=0; i<5; ++i) p[i]='A'+i; // 泄漏的5个字节内存为"ABCDE"
}
void leakInDll()
{
char *p = new char[16];
strcpy(p, "dll leaking!"); // 调用dll函数,在dll中分配一个16字节的空间保存"dll leaking!",且不释放内存。
HMODULE hMod = LoadLibrary(_T("Dll.dll"));
if (hMod) {
FARPROC2 hLeakInDll = (FARPROC2) GetProcAddress(hMod, "dllLeak");
hLeakInDll(16, p);
}
}
下面是Dll中被调用的函数代码
void dllLeak(int n, char * st)
{
char *p = new char[n];
for (int i=0; i<n; ++i) p[i] = st[i];
}
运行完毕之后的输出为:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 57 at 0x01C899D8: 16 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
64 6C 6C 20 6C 65 61 6B 69 6E 67 21 00 CD CD CD dll.leak ing!....
---------- Block 56 at 0x01C89990: 5 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
41 42 43 44 45 ABCDE... ........
---------- Block 55 at 0x01C89928: 40 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ........ ........
04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 ........ ........
08 00 00 00 09 00 00 00 ........ ........
Visual Leak Detector detected 3 memory leaks.
可以看到,VLD检测出了分别在主程序函数t_main、leak5Bytes以及Dll.dll中dllLeak的内存泄漏,并显示了泄漏内存的内容。
2. LeakDiag
之前的VLD必须和源代码一起编译,若是遇到主程序源码不方便重新编译的情况,则可以选择使用LeakDiag。LeakDiag是微软的一款内存泄漏检测工具,鉴于已经有大牛写了比较详尽的使用说明,我就不再赘述,直接引用大牛的博客地址:
http://www.cppblog.com/sandy/archive/2008/08/18/59260.html
LeakDiag下载地址:
ftp://ftp.microsoft.com/PSS/Tools/Developer%20Support%20Tools/LeakDiag/
工具:
1. IBM Rational PurifyPlus是一套完整的运行时分析工具,旨在提高应用程序的可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
网站:
http://www-128.ibm.com/developerworks/rational/products/purifyplus
从这里可以得到 IBM Rational 的试用版(DVD),
http://www-128.ibm.com/developerworks/cn/offers/sek/index.html
2. BoundsChecker
BoundsChecker是一个C++运行时错误检测和调试工具。它通过在VisualStudio内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚,详细的程序错误分析,许多是对C++独有的并且在
static,stack和heap内存中检测和诊断错误,以及发现内存和资源的泄漏。3. http://www.parasoft.com/ 4. http://www.glowcode.com/
1.Visual Leak Detector 1.0 (VLD)
这是一个小巧内存检测工具,是为Visual C++用户设计的。其特色为:
简单易用,只需要在需要进行内存泄漏检测的的主程序代码中加入#include "VLD.h“,并将编译好的Lib文件放入默认的库目录,然后在Visual C++用Debug模式编译运行程序,程序运行结束后便可在Visual C++的输出窗口看到内存泄露检测结果。
通过宏定义控制测试行为,如报告的详略等。
支持Windows X64。
检测报告很直观,甚至能显示泄漏内存的内容。
下面是一段用于演示VLD功能的代码:
TestVLD.cpp
#include "stdafx.h"
#include "vld.h"
#include "afx.h"
#include "string.h"
typedef void(*FARPROC2)(int, char*); // 用于调用dll中函数的指针
void leak5Bytes(); // 泄漏5个字节内容为"ABCDE"内存
void leakInDll(); // 调用dll中会造成内存泄漏函数
int _tmain(int argc, _TCHAR* argv[])
{
int * p = new int[10];
for (int i=0; i<10; ++i) p[i]=i; // 泄漏10个int的内存,内容分别为0到9
leak5Bytes(); // 泄漏5个字节内存
leakInDll(); // 调用dll中会造成内存泄泄漏的函数
return 0;
}
void leak5Bytes()
{
char * p = new char[5];
for (int i=0; i<5; ++i) p[i]='A'+i; // 泄漏的5个字节内存为"ABCDE"
}
void leakInDll()
{
char *p = new char[16];
strcpy(p, "dll leaking!"); // 调用dll函数,在dll中分配一个16字节的空间保存"dll leaking!",且不释放内存。
HMODULE hMod = LoadLibrary(_T("Dll.dll"));
if (hMod) {
FARPROC2 hLeakInDll = (FARPROC2) GetProcAddress(hMod, "dllLeak");
hLeakInDll(16, p);
}
}
下面是Dll中被调用的函数代码
void dllLeak(int n, char * st)
{
char *p = new char[n];
for (int i=0; i<n; ++i) p[i] = st[i];
}
运行完毕之后的输出为:
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 57 at 0x01C899D8: 16 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
64 6C 6C 20 6C 65 61 6B 69 6E 67 21 00 CD CD CD dll.leak ing!....
---------- Block 56 at 0x01C89990: 5 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
41 42 43 44 45 ABCDE... ........
---------- Block 55 at 0x01C89928: 40 bytes ----------
Call Stack:
f:\rtm\vctools\crt_bld\self_x86\crt\src\new2.cpp (27): operator new[]
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (318): __tmainCRTStartup
f:\rtm\vctools\crt_bld\self_x86\crt\src\crt0.c (187): wmainCRTStartup
0x7D517D2A (File and line number not available): BaseProcessInitPostImport
Data:
00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ........ ........
04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 ........ ........
08 00 00 00 09 00 00 00 ........ ........
Visual Leak Detector detected 3 memory leaks.
可以看到,VLD检测出了分别在主程序函数t_main、leak5Bytes以及Dll.dll中dllLeak的内存泄漏,并显示了泄漏内存的内容。
2. LeakDiag
之前的VLD必须和源代码一起编译,若是遇到主程序源码不方便重新编译的情况,则可以选择使用LeakDiag。LeakDiag是微软的一款内存泄漏检测工具,鉴于已经有大牛写了比较详尽的使用说明,我就不再赘述,直接引用大牛的博客地址:
http://www.cppblog.com/sandy/archive/2008/08/18/59260.html
LeakDiag下载地址:
ftp://ftp.microsoft.com/PSS/Tools/Developer%20Support%20Tools/LeakDiag/
工具:
1. IBM Rational PurifyPlus是一套完整的运行时分析工具,旨在提高应用程序的可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
网站:
http://www-128.ibm.com/developerworks/rational/products/purifyplus
从这里可以得到 IBM Rational 的试用版(DVD),
http://www-128.ibm.com/developerworks/cn/offers/sek/index.html
2. BoundsChecker
BoundsChecker是一个C++运行时错误检测和调试工具。它通过在VisualStudio内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚,详细的程序错误分析,许多是对C++独有的并且在
static,stack和heap内存中检测和诊断错误,以及发现内存和资源的泄漏。3. http://www.parasoft.com/ 4. http://www.glowcode.com/