运行单元测试时检测内存泄漏

4
我有一个Win32 C++应用程序,带有一套单元测试。在单元测试完成后,我想自动生成任何未释放内存的人类可读报告。理想情况下,报告将具有每个未释放分配的文件和行号信息的堆栈。最好按一致的顺序生成它们,以便轻松地从一次运行到下一次进行差异比较。(基本上,我想要valgrind --leak-check=full的结果,但在Windows上)。
我已经成功地使用UMDH从运行中的进程获取此类信息,但该工具似乎只能在附加到现有进程时才能工作。我希望每次运行我的单元测试时都会自动发生这种情况。
是否有可以做到这一点的工具?如果有,我该如何使用它?
谢谢!
5个回答

4
为了获取这种信息,我们会覆盖 new/delete 和 malloc/free,并提供自己的堆实现来存储分配时的堆栈跟踪,并在堆销毁时生成报告(以及添加哨兵以检测缓冲区溢出)。
第一次执行此操作需要做很多工作。 这个人编写了一个处理所有困难部分的免费工具 - 我自己没有尝试过,但他编写它的解释在编写自己的工具时很有用。

1
如果您正在使用MSVC,Microsoft的Debug堆函数可以用于生成您想要的报告,但它可能不像您希望的那样自动化(您可能需要编写一些自定义代码):
_CrtSetReportMode
_CrtSetReportFile
_CrtMemState    
_CrtMemCheckpoint
_CrtMemDumpStatistics
_CrtSetReportFile
_CrtSetDbgFlag

在一个较大的项目中打开过多这些东西,会导致事情变得异常缓慢。 - Harald Scheirich

0

你可以定义DEBUG_NEW,这会打开一些泄漏检测功能,但需要在包含任何系统包含文件之前定义它。它仅使用new运算符检查泄漏,当然你必须重新编译代码,所以不能像valgrind那样附加它。

在此处查看更多信息:

http://msdn.microsoft.com/en-us/library/tz7sxz99(VS.80).aspx


0

我曾经做过这个,但它并不是完全自动化的。我现在无法访问那段代码,但是这是我的想法:

我使用了 Mike B 提到的 调试函数(顺便说一下,它们只在 Debug 模式下工作)。

测试运行器会运行所有测试两次,因为在第一次运行时会为全局变量分配内存。第二次运行时,在每个测试之前和之后检查已分配块的总数(我认为可以在 setUp() 和 tearDown() 中进行)。如果数量不同,则表示存在内存泄漏,并且测试将以适当的消息失败。当然,如果测试本身失败,您应该保留其错误消息。现在要找到泄漏,我必须使用 pBlockHeader 读取最后一个分配的块分配号,然后使用 _CrtSetBreakAlloc 在其上设置断点并再次运行。

更多相关信息请参见:http://levsblog.wordpress.com/2008/10/31/unit-testing-memory-leaks/


0

我试过了Mike B指出的CRT Debug Heap函数,但最终只得到泄漏内存的地址并不满足我的需求。像UMDH提供的获取栈信息可以加速调试。因此,现在我的main()函数中,在运行测试前后使用CreateProcess启动UMDH进行堆快照。我还编写了一个简单的批处理文件,运行测试驱动程序然后对比堆快照。所以,我只需启动批处理文件,就可以一次性获取测试结果和任何未释放分配的完整堆栈的文本文件。

UMDH会捕获到很多错误的正向事件,因此也许将CrtDebug和我现在做的事情混合起来会是更好的解决方案。但是,目前我对我所拥有的感到满意。

现在如果我能找到一种检测是否没有关闭任何句柄的方法就好了...


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