【问题标题】:Visual Studio 2008 (C++) memory leak detection not showing file/method location - how to get that to work?Visual Studio 2008 (C++) 内存泄漏检测不显示文件/方法位置 - 如何让它工作?
【发布时间】:2009-10-14 17:43:08
【问题描述】:

我正在使用instructions found here 来尝试查找 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 向导工作。

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

编辑:

I also tried visual leak detector - 没有成功。

很奇怪。

编辑

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

【问题讨论】:

  • 尝试解密器。它应该对你有帮助。

标签: c++ visual-studio-2008 memory-leaks


【解决方案1】:

您确定泄漏的代码使用的是 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 的 redef 看看会发生什么。
  • 我认为这可以解决我的问题,但是在项目中编译 boost 的东西时它会窒息。我想我将不得不以某种方式分离出提升问题。
  • 我也遇到过。一些 boost 库会覆盖 operator new,因此您必须在 之后执行 DEBUG_NEW 定义,包括 boost 标头或至少其中一些。
  • 我希望这不是解决方法......好吧,除了卷起袖子之外别无他法。谢谢
  • 现在我想我知道为什么要删除它了...有人为项目添加了 boost 并取出了 debug_new 我猜。我不明白为什么它不会在那里。
【解决方案2】:

给定运行结束时的泄漏列表,例如:

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);
...

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

【讨论】:

    猜你喜欢
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多