为什么_CrtSetDumpClient不工作?

我正在使用Visual Studio Express 2013 for Windows Desktop用C编写的Windows命令行程序。 当在debugging模式下编译时,我真的很喜欢我的程序检测内存泄漏,并在标准错误或标准输出上打印它们,所以它们在我的面前。

通过调用_CrtDumpMemoryLeaks ,我可以得到内存泄漏信息打印出来的Visual Studio中的debugging输出(您可以在输出窗格中find)。 基于MSDN文档,我认为我可以添加一个调用_CrtSetDumpClient为了获得访问被转储的数据,然后打印到stderr。

这里是我用来testing这个问题的代码:

#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中创build了一个新的Visual C ++ Win32控制台应用程序项目,将此代码粘贴到项目中,禁用了预编译头文件,确保IDE处于debugging模式并生成。 如果我按F5(开始debugging命令)运行它,那么我可以在Visual Studio的debugging窗口中看到以下输出,这是很好的:

 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函数根本不被调用?

Solutions Collecting From Web of "为什么_CrtSetDumpClient不工作?"

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-> nBlockUse)== _CLIENT_BLOCK。

调用malloc ,只分配_NORMAL_BLOCK

您可以调用_malloc_dbg(44, _CLIENT_BLOCK, filename, line)http://msdn.microsoft.com/en-us/library/faz3a37z.aspx

那么你的函数将被调用。

当然,微软可能已经在_CrtSetDumpClient文档中提到了这个,但是这太容易了;)

根据MSDN 文档

 _CrtSetDumpClient: Installs an application-defined function to dump _CLIENT_BLOCK type memory blocks 

这里的关键字是_CLIENT_BLOCK 。 这里记录了堆上的各种块 。 一个简单的malloc调用创建一个_NORMAL_BLOCK ,因此你的函数不被调用。