C++ 如何忽略来自_CrtDumpMemoryLeaks的假阳性内存泄漏?

C++ 如何忽略来自_CrtDumpMemoryLeaks的假阳性内存泄漏?,c++,memory,static,memory-leaks,C++,Memory,Static,Memory Leaks,似乎每当存在静态对象时,_CrtDumpMemoryLeaks就会返回一个假阳性,声称它正在泄漏内存。我知道这是因为它们在main()函数(或WinMain)之后才会被销毁。但有没有办法避免这种情况?我使用VS2008。不是一个直接的解决方案,但总的来说,我发现将尽可能多的分配移出静态初始化时间是值得的。它通常会导致麻烦(初始化顺序、反初始化顺序等) 如果证明这太难,您可以在main()的开头调用\u CrtMemDumpAllObjectsSince和\u CrtMemDumpAllObjec

似乎每当存在静态对象时,_CrtDumpMemoryLeaks就会返回一个假阳性,声称它正在泄漏内存。我知道这是因为它们在main()函数(或WinMain)之后才会被销毁。但有没有办法避免这种情况?我使用VS2008。

不是一个直接的解决方案,但总的来说,我发现将尽可能多的分配移出静态初始化时间是值得的。它通常会导致麻烦(初始化顺序、反初始化顺序等)

如果证明这太难,您可以在
main()
的开头调用
\u CrtMemDumpAllObjectsSince
\u CrtMemDumpAllObjectsSince

最后。

您能在每次需要列表时拍摄当前分配对象的快照吗?如果是这样,则在查找操作中发生的泄漏时,可以从列表中删除最初分配的对象。在过去,我用它来发现增量泄漏

另一个解决方案可能是对泄漏进行排序,而只考虑同一行代码的重复。这应该排除静态变量泄漏

雅各布你说:

似乎每当存在静态对象时,_CrtDumpMemoryLeaks就会返回一个假阳性,声称它正在泄漏内存

我认为这是不对的编辑:静态对象不是在堆上创建的结束编辑:\u CrtDumpMemoryLeaks仅覆盖crt堆内存。因此,这些对象不应返回误报。 但是,如果静态变量是本身包含一些堆内存的对象(例如,如果它们使用
操作符new()
动态创建成员对象),则这是另一回事


2)考虑在程序执行结束时使用YCRTBGGLIXIGCHECKEXDF来激活内存泄漏检查(这里描述:)。我想,即使在静态变量终止之后,也会进行内存泄漏检查。

Ach。如果您确定
\u CrtDumpMemoryLeaks()
在撒谎,那么您可能是正确的。我看到的大多数所谓的内存泄漏都是由于对
\u crtdumpmomeryleaks()
的非直接调用造成的。我完全同意以下几点:<代码>\u CrtDumpMemoryLeaks()转储所有打开的句柄。但是您的程序可能已经有了打开的句柄,所以请确保只有在释放所有句柄后才调用
\u crtdumpmomeryleaks()
。请参阅以了解更多信息。

我发现,如果您告诉它在程序终止后自动检查内存,它将允许计算所有静态对象。我使用log4cxx和boost在静态块中进行大量分配,这修复了我的“误报”

在main()开头的某个地方添加以下行,而不是调用_crtdumpmomeryleaks:

有关用法和宏的更多详细信息,请参阅MSDN文章:


老问题,但我有答案。我能够将报告分为误报和真实内存泄漏。在我的主函数中,我初始化内存调试,并在应用程序真正开始时生成真正的内存泄漏(从不删除PCSTART):

我的申请完成后,报告包含

Detected memory leaks!
Dumping objects ->
{15554} normal block at 0x00000000009CB7C0, 80 bytes long.
Data: <                > DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD
{14006} normal block at 0x00000000009CB360, 17 bytes long.
Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74 
{13998} normal block at 0x00000000009BF4B0, 32 bytes long.
Data: < ^              > E0 5E 9B 00 00 00 00 00 F0 7F 9C 00 00 00 00 00 
{13997} normal block at 0x00000000009CA4B0, 8 bytes long.
Data: <        > 14 00 00 00 00 00 00 00 
{13982} normal block at 0x00000000009CB7C0, 16 bytes long.
Data: <   @            > D0 DD D6 40 01 00 00 00 90 08 9C 00 00 00 00 00

...

Object dump complete.
检测到内存泄漏!
转储对象->
0x00000000009CB7C0处的{15554}正常块,长80字节。
数据:<>dddddddddddddddddddddddddddddddddddddddddddddddddd
0x00000000009CB360处的{14006}正常块,17字节长。
资料:44796E616D69634865617053747274
0x00000000009BF4B0处的{13998}正常块,32字节长。
数据:<^>E0 5E 9B 00 F0 7F 9C 00 00
0x00000000009CA4B0处的{13997}正常块,8字节长。
数据:<>14 00 00
0x00000000009CB7C0处的{13982}正常块,16字节长。
数据:<@>D0 DD D6 40 01 00 90 08 9C 00 00 00
...
对象转储完成。
现在看一看第行“数据:44796E616D69634865617053747274”

以下所有reportet泄漏均为误报,以上均为真实泄漏。 误报并不意味着没有泄漏(它可能是一个静态链接库,在启动时分配堆,并且永远不会释放堆),但是您无法消除泄漏,这根本没有问题

自从我发明了这种方法,我就再也没有泄漏的应用程序了。
我在这里提供了这一点,希望这有助于其他开发人员获得稳定的应用程序。

我可以推荐VisualLeakDetector(它是免费的),而不是使用VS中内置的东西。我的问题是使用带有开放源代码库的_CrtDumpMemoryLeaks,它创建了990行输出,据我所知都是误报,还有一些来自boost的东西。VLD忽略了这些,并正确地报告了我为测试添加的一些泄漏,包括在从C#调用的本机DLL中。

堆栈上没有分配静态对象。@Billy:谢谢你的更正…假设你是对的。但是,它们也没有被分配到堆上,是吗?我希望你们现在已经知道静态对象存储在哪里了。我仍然发现boost
boost\u LOG\u这个代码的内存泄漏,琐碎(错误)链接死了。此外,
\u crtdumpmomeryleaks
不监视句柄。它严格地引用调试堆中的内存块。由静态初始值设定项中使用的自己的类引起的泄漏也可能在“DynamicHeapStart”行下方报告,即据称是误报。如果模块的代码或链接顺序发生变化,它们的相对位置可能会发生变化。
int main()
{   
   _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
   char* pcDynamicHeapStart = new char[ 17u ];
   strcpy_s( pcDynamicHeapStart, 17u, "DynamicHeapStart" );

   ...
Detected memory leaks!
Dumping objects ->
{15554} normal block at 0x00000000009CB7C0, 80 bytes long.
Data: <                > DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD
{14006} normal block at 0x00000000009CB360, 17 bytes long.
Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74 
{13998} normal block at 0x00000000009BF4B0, 32 bytes long.
Data: < ^              > E0 5E 9B 00 00 00 00 00 F0 7F 9C 00 00 00 00 00 
{13997} normal block at 0x00000000009CA4B0, 8 bytes long.
Data: <        > 14 00 00 00 00 00 00 00 
{13982} normal block at 0x00000000009CB7C0, 16 bytes long.
Data: <   @            > D0 DD D6 40 01 00 00 00 90 08 9C 00 00 00 00 00

...

Object dump complete.