Visual Studio 2008(C ++)内存泄漏检测未显示文件/方法位置 - 如何使其工作?

10
我正在使用从这里找到的指南来寻找Win32应用程序中的内存泄漏。如所描述的那样,我放置了

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

我在一个文件的顶部(包含WINAPI _tWinMain的cpp文件)和winmain的退出点添加了代码行

_CrtDumpMemoryLeaks();

很遗憾,我看不到泄漏的行号/位置(但是我可以得到一个泄漏清单)。

我也尝试着放置

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 
_CrtSetReportMode ( _CRT_ERROR, _CRTDBG_MODE_DEBUG); 

在WinMain的开头 - 不过还是没有运气。

我觉得这很奇怪,因为我通常不会有找到泄漏或自动报告它们的问题。

这是一个我正在为新雇主工作的庞大而古老的遗留应用程序。在过去,我通常使用标准的VS向导进行工作。

有没有建议如何获取导致泄漏的源代码行/方法?(或者至少是“new”调用的行?

编辑:

我也尝试了Visual Leak Detector,但没有成功。

非常奇怪。

编辑

我尝试使用下面列出的new的重新定义,但当编译boost时会出现错误。


1
尝试使用Deleaker。它应该会对你有所帮助。 - John Smith
2个回答

6

您确定正在泄漏的代码使用了CRT调试分配例程吗?这需要使用malloc()new(而不是LocalAllocGlobalAlloc,某些自定义块分配器等),并且在包含CRT头文件时必须定义_DEBUG(我想)。

为了获取泄漏的源代码行,您需要在发生分配的每个位置处定义DEBUG_NEW。这是因为为了跟踪它们,每个分配都必须被替换为一个调用,其中包括__FILE____LINE__。向导的标准定义看起来像这样:

#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

这不处理malloc,如果您要调试的代码使用malloc而不是new,可能会有类似的咒语。
如果您正在使用预编译头文件,您可以将其放在预编译头文件中,它将影响该项目中的所有源文件。

是的,没有使用globalalloc。这对我来说非常奇怪。我会尝试添加new的重新定义并查看发生了什么。 - Tim
我以为这会解决我的问题,但在编译项目中的boost内容时出现了问题。我想我必须想办法将boost问题分离出来。 - Tim
6
我也遇到过这个问题。一些 Boost 库会覆盖 operator new,因此您必须在包含 Boost 标头之后或至少其中一些标头之后进行 DEBUG_NEW 定义。 - Tim Sylvester
我希望那不是解决方法...好的,现在只能卷起袖子干了。谢谢。 - Tim
现在我想我知道为什么这个被移除了... 有人添加了 boost 到项目中,我猜是为了去掉 debug_new。不然的话,我无法理解为什么它会不存在。 - Tim

1

给定一组泄漏列表,类似于:

Detected memory leaks!
Dumping objects ->
{12913} normal block at 0x000002BC648BB9D0, 82 bytes long.
 Data: <h t t p : / / a > 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 61 00
{12912} normal block at 0x000002BC648B8030, 24 bytes long.
 Data: <0  d      `     > 30 CD 89 64 BC 02 00 00 D8 02 60 E5 F7 7F 00 00
...

使用_CrtSetBreakAlloc很容易找到这些内存块的分配位置,例如要在分配号码为12913时停止分配,需要输入:

...
_CrtSetBreakAlloc(12913);
...

在分配发生之前的代码中:单元测试的开始或主函数是一些可能的示例。现在,当分配编号为12913的块被分配,并且从调试器中的调用堆栈中很容易找到分配位置时,void* __CRTDECL operator new(size_t const size)将抛出异常。


抱歉多年后才问,如果分配号码不是静态的,在重新运行时每次都会更改怎么办? - Zrn-dev
@Zrn-dev 首先,你需要消除这种随机性(我知道这比做起来容易),否则你需要其他工具(比如valgrind)。 - ead

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接