包含vld.h的时候,使用pragma comment链接vldddlib(采用预编译指令,根据不同的工程链接不同的lib)
通过全局变量
VisualLeakDetector visualleakdetector;
的构造和析构来启动和终止内存跟踪
构造函数中使用_CrtSetAllocHook函数设置钩子函数捕获_HOOK_ALLOC、_HOOK_FREE、_HOOK_REALLOC等事件。
设置钩子函数
m_poldhook = _CrtSetAllocHook(allochook);
nt VisualLeakDetector::allochook (int type, void *pdata, size_t size, int use, long request, const unsigned char *file, int line)
...
switch (type) {
case _HOOK_ALLOC:
visualleakdetector.hookmalloc(request);
break;
case _HOOK_FREE:
visualleakdetector.hookfree(pdata);
break;
case _HOOK_REALLOC:
visualleakdetector.hookrealloc(pdata, request);
break;
...
释放内容时,从堆栈中清除对应的分配请求
void VisualLeakDetector::hookfree (const void *pdata)
{
long request = pHdr(pdata)->lRequest;
m_mallocmap->erase(request);
}
保存分配请求在堆栈中
void VisualLeakDetector::hookmalloc (long request)
{
CallStack *callstack;
if (!enabled()) {
// Memory leak detection is disabled. Don't track allocations.
return;
}
callstack = m_mallocmap->insert(request);
getstacktrace(callstack);
}
void VisualLeakDetector::hookrealloc (const void *pdata, long request)
{
// Do a free, then do a malloc.
hookfree(pdata);
hookmalloc(request);
}
析构时,堆栈中剩余的内容就是泄露的内存
报告内存泄露情况时,使用dbghelp.dll中的如下函数获取分配内存时的函数调用堆栈,函数名称,所在源码文件以及行号等内容
StackWalk64;
SymCleanup;
SymFromAddr;
SymFunctionTableAccess64;
SymGetModuleBase64;
SymGetLineFromAddr64;
SymInitialize;
SymSetOptions;
这些函数的含义及使用情况参加MSDN