检测到内存泄漏。

18
在我的 wxWidgets 应用程序中,以调试模式运行时,在 Visual Studio 2010 的输出中看到了以下消息。应用程序正常运行,只有在关闭后才看到此提示。

检测到内存泄漏!

正在转储对象 ->

{9554} normal block at 0x003CDCC0, 长度为44字节。
数据: < e n d > 20 C1 65 01 01 00 00 00 6E 00 00 00 9C CE 64 01

{9553} normal block at 0x003CDB58, 长度为8字节。

数据: < D e < > 44 BD 65 01 C0 DC 3C 00
{9552} normal block at 0x003CDC50, 长度为48字节。

数据: < e > A0 95 65 01 01 00 00 00 19 00 00 00 19 00 00 00

对象转储完成。

在我的程序中,我没有显式分配内存,但是 wxWidgets 框架会这样做。我第一次得到这样的消息,并不知道确切原因。
如何消除此内存泄漏?

1
请发布您的代码,最好是一个能够重现问题的最小程序。 - user1071136
很遗憾,我无法发布一个最小程序。因为它是一个带有多个文件和GUI框架的GUI程序。我不知道是什么原因导致了这个问题。因为我从未使用过newmalloc - Vinayak Garg
我只是担心你会得到更多的猜测而不是答案 :) - user1071136
5个回答

42

您只需要在主函数的开头添加以下几行代码。通过添加此标志,Visual Studio 将在创建内存泄漏的代码行中断点。

    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    _CrtSetBreakAlloc(9554);
    _CrtSetBreakAlloc(9553);
    _CrtSetBreakAlloc(9552);

请确保您拥有正确的对象正常块地址,因为它们可能会发生更改,并确保您正在编译_DEBUG。

另请参阅:_CrtSetDbgFlag_CrtSetBreakAlloc


1
谢谢,对我来说真正起作用的是将 _crtBreakAlloc = 9609; 添加为第一条语句。对于 wxWidgets,我需要将它添加到主应用程序的 OnInit() 函数中。 - Vinayak Garg
5
你好,9609是怎么想出来的? - blue piranha
3
@bluepiranha提到的是括号中开头的数字。所以在他的情况下,他在{9609}处有一个报告。(我知道这是一个旧评论;但这也是为像我这样寻找这些信息的人准备的)。 - allen1
值得注意的是,如果您手动调用 _CrtCheckMemory() 而不是使用调试标志在程序退出时运行它,则使用堆的静态变量将显示为泄漏。而且 _CrtSetBreakAlloc() 不会触发它们,因为它们是在 main() 运行之前初始化的。 - Phi

0

也许某些类型的静态实例仍由框架分配。尝试使用像“devpartner”这样的分析工具来解决它。


Visual Studio 的消息能用来获取帮助吗? - Vinayak Garg
@VinayakGarg 这可以帮助一点,但是有非常有限的用处。Data实际上是内存地址的内容,通过它你可以猜测内存的用途,并猜测它被分配在哪里。 - fefe
@CJohnson 你是对的,他需要其他的分析工具我会进行更改:) 谢谢。 - AlexTheo

0
  1. 永远不要“假设”你的代码是内存泄漏免疫的。除非你是编程半神,否则没有人能够完全避免可能写出内存泄漏的代码。

  2. 你可以使用像Bounds Checker(来自Microfocus)这样的工具来帮助识别内存泄漏,因为它会给你一个调用堆栈。从调试CRT得到的内存泄漏报告只告诉你在特定地址发生了内存泄漏。像Bounds Checker这样的产品将为您提供该内存泄漏的调用堆栈以及许多其他好处。市场上还有其他内存泄漏工具,但我不会在此列出。

  3. 如果你确定内存泄漏是由“wxWidgets”引起的,那么也许你应该通知该库的作者,也许他们会修复它(并提供适当的重现步骤)。


3
我从未说过我的代码不会内存泄漏,只是我在代码中没有使用new或malloc。也许我应该尝试在wxWidgets网站上提问。 - Vinayak Garg

0

这个维基建议在每个源文件的所有其他头文件包含之后添加以下内容:

#ifdef __WXMSW__
    #include <wx/msw/msvcrt.h>      // redefines the new() operator 
#endif

这将导致在程序结束时报告泄漏。

更具体地说,请确保您调用->Destroy()来销毁所有使用new创建的对象(除了您的顶层窗口之外)。


0
如果vs报告的泄漏位置每次都相同,您可以设置数据断点以查看何时更改了此内存,并希望找出是谁分配了此内存。

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