我正在使用Visual Studio Express 2013 for Windows Desktop编写用C编写的Windows命令行程序。在调试模式下编译时,我真的希望我的程序检测内存泄漏并将其打印在标准错误或标准输出上,这样它们就在我面前。
通过调用_CrtDumpMemoryLeaks,我可以将内存泄漏信息打印到Visual Studio中的Debug输出(您可以在“输出”窗格下找到)。根据MSDN文档,我认为我可以添加对_CrtSetDumpClient的调用,以便访问被转储的数据,然后将其打印到stderr。
以下是我用来测试此问题的代码:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <stdio.h>
#include <crtdbg.h>
void dumpClient(void * userPortion, size_t blockSize)
{
printf("memory leak: %d\n", blockSize);
}
int main(int argc, char ** argv)
{
printf("hello\n");
_CrtSetDumpClient(&dumpClient);
malloc(44);
_CrtDumpMemoryLeaks();
return 0;
}
我在Visual Studio中创建了一个新的Visual C ++ Win32控制台应用程序项目,将此代码粘贴到项目中,禁用预编译头文件,确保IDE处于调试模式并构建。如果我按F5(开始调试命令)运行它,那么我可以在Visual Studio的调试窗口中看到以下输出,这很好:
Detected memory leaks!
Dumping objects ->
c:\users\david\documents\scraps\test_vc++\testvc\testvc.cpp(15) : {81} normal block at 0x0120A500, 44 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
The program '[3868] TestVC.exe' has exited with code 0 (0x0).
但是,如果我在dumpClient
内设置断点,我可以看到它永远不会被调用。此外,如果我从命令提示符运行该程序,它只会打印hello
。我希望看到的期望的输出是:
hello
memory leak: 44
有谁知道为什么根本没有调用dumpClient
函数?
答案 0 :(得分:1)
TL; DR
您可以拨打_malloc_dbg(44, _CLIENT_BLOCK, filename, line)
而不是malloc
。
通过查看dbgheap.c,您可以看到可以调用函数的唯一方法是:
if (_BLOCK_TYPE(pHead->nBlockUse) == _CLIENT_BLOCK)
{
_RPT3(_CRT_WARN, "client block at 0x%p, subtype %x, %Iu bytes long.\n",
(BYTE *)pbData(pHead), _BLOCK_SUBTYPE(pHead->nBlockUse), pHead->nDataSize);
if (_pfnDumpClient && !__crtIsBadReadPtr(pbData(pHead), pHead->nDataSize))
{
(*_pfnDumpClient)((void *)pbData(pHead), pHead->nDataSize);
}
else
{
_printMemBlockData(plocinfo, pHead);
}
}
所以你必须有_BLOCK_TYPE(pHead-&gt; nBlockUse)== _CLIENT_BLOCK。
致电malloc
时,您只需分配_NORMAL_BLOCK
s。
您可以致电_malloc_dbg(44, _CLIENT_BLOCK, filename, line)
。
http://msdn.microsoft.com/en-us/library/faz3a37z.aspx
然后你的函数将被调用。
当然,微软可以在_CrtSetDumpClient
文档中提到这一点,但这样做太容易了;)
答案 1 :(得分:0)
根据MSDN documentation
_CrtSetDumpClient: Installs an application-defined function to
dump _CLIENT_BLOCK type memory blocks
此处的关键字为 _CLIENT_BLOCK 。这里记录了各种类型的blocks on heap。一个简单的malloc调用会创建一个 _NORMAL_BLOCK ,因此不会调用您的函数。