似乎每当存在静态对象时,_CrtDumpMemoryLeaks 函数都会返回一个错误的结果,声称内存泄漏。我知道这是因为它们直到 main() 或 WinMain 函数执行完毕才被销毁。但有没有什么方法可以避免这种情况?我使用的是VS2008。
似乎每当存在静态对象时,_CrtDumpMemoryLeaks 函数都会返回一个错误的结果,声称内存泄漏。我知道这是因为它们直到 main() 或 WinMain 函数执行完毕才被销毁。但有没有什么方法可以避免这种情况?我使用的是VS2008。
我发现如果在程序终止后告诉它自动检查内存,它就可以将所有静态对象计算在内。我正在使用log4cxx和boost,它们在静态块中进行了大量分配,这解决了我的“误报”问题...
在main()的开头添加以下行,而不是调用_CrtDumpMemoryLeaks:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
有关用法和宏的更多详细信息,请参阅MSDN文章:
http://msdn.microsoft.com/en-us/library/5at7yxcs(v=vs.71).aspx
main()
函数开始时调用 _CrtMemCheckpoint
(http://msdn.microsoft.com/en-us/library/h3z85t43%28VS.80%29.aspx),并在结束时调用 _CrtMemDumpAllObjectsSince
。虽然这是一个旧问题,但我有一个答案。我能够将报告分为假阳性和真正的内存泄漏。在我的主函数中,我初始化了内存调试并在应用程序的最开始生成了一个真正的内存泄漏(从不删除pcDynamicHeapStart):
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.
现在看一下 "Data: <DynamicHeapStart> 44 79 6E 61 6D 69 63 48 65 61 70 53 74 61 72 74" 这一行。
以下所有报告的泄漏都是误报,以上所有泄漏都是真正的泄漏。 误报并不意味着没有泄漏(可能是静态链接库在启动时分配堆内存并且从不释放),但你无法排除泄漏,这并没有问题。
自从我发明了这种方法后,我的应用程序再也没有泄漏过。 我在这里提供它,希望这有助于其他开发人员获得稳定的应用程序。
1) 你说:
似乎每当有静态对象时,_CrtDumpMemoryLeaks都会返回一个错误的正面结果,声称它正在泄漏内存。
我认为这是不正确的。编辑:静态对象不是在堆上创建的。结束编辑:_CrtDumpMemoryLeaks仅涵盖crt堆内存。因此,这些对象不应该返回错误的正面结果。
但是,如果静态变量是对象,它们本身持有一些堆内存(例如,如果它们使用operator new()
动态创建成员对象),那就是另一回事了。
2) 考虑使用_CRTDBG_LEAK_CHECK_DF以在程序执行结束时激活内存泄漏检查(在此处描述:http://msdn.microsoft.com/en-us/library/d41t22sb(VS.80).aspx)。我想这样做后,即使在静态变量终止后也会进行内存泄漏检查。
每次需要列表时,您能否拍摄当前分配的对象快照?如果可以,当您寻找操作中发生的泄漏时,可以从列表中删除最初分配的对象。过去,我曾使用此方法查找增量泄漏。
另一个解决方案可能是对泄漏进行排序,并仅考虑相同代码行的重复项。这应该排除静态变量泄漏。
Jacob
_CrtDumpMemoryLeaks()
在撒谎,那么你可能是正确的。我看到的大多数所谓的内存泄漏都是由于对 _CrtDumpMemoryLeaks()
的不正确调用引起的。我完全同意以下观点;_CrtDumpMemoryLeaks()
转储所有打开的句柄。但是你的程序可能已经有了打开的句柄,所以请确保只在所有句柄释放后调用 _CrtDumpMemoryLeaks()
。请参阅 http://www.scottleckie.com/2010/08/_crtdumpmemoryleaks-and-related-fun/ 以获取更多信息。_CrtDumpMemoryLeaks
不监视句柄。它严格参考调试堆中的内存块。 - IInspectable
BOOST_LOG_TRIVIAL(error) << "Module: ";
设置 _CrtSetDbgFlag 也没有起到帮助作用。您有任何想法吗? - Pritesh Acharya