代码之家  ›  专栏  ›  技术社区  ›  twk Mark Adler

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

  •  4
  • twk Mark Adler  · 技术社区  · 16 年前

    我有一个Win32 C++应用程序,带有一套单元测试。在单元测试完成运行后,我希望自动生成有关任何未释放内存的可读报告。理想情况下,报告将有一个堆栈,其中包含每个未释放分配的文件和行号信息。将它们以一致的顺序生成是很好的,这样可以很容易地将其从一次运行区分到下一次运行。(基本上,我希望valgrind的结果——泄漏检查=满,但在Windows上)。

    我已经成功地从运行进程中获得了这种信息,但是这个工具似乎只有在附加到现有进程时才起作用。我希望每次运行单元测试时都自动发生这种情况。

    有什么工具可以做到这一点吗?如果是,我如何使用它?

    谢谢!

    5 回复  |  直到 16 年前
        1
  •  4
  •   moonshadow    16 年前

    为了获得这类信息,我们重写new/delete和malloc/free,提供我们自己的堆实现,在分配时存储stacktrace,并在堆被破坏时生成报告(以及添加sentinel以检测缓冲区溢出)。

    这是你第一次做这件事时做的相当多的工作。 This guy 写了一个处理所有困难的免费软件工具-我自己没有试过,但他如何写的解释是有用的滚动你自己。

        2
  •  1
  •   Michael Burr    16 年前

    如果您使用的是MSVC,则可以使用Microsoft的调试堆函数生成所需的报告,但它可能没有您希望的那样自动(您可能需要编写一些自定义代码):

    _CrtSetReportMode
    _CrtSetReportFile
    _CrtMemState    
    _CrtMemCheckpoint
    _CrtMemDumpStatistics
    _CrtSetReportFile
    _CrtSetDbgFlag
    
        3
  •  0
  •   KPexEA    16 年前

    您可以定义debug_new并打开一些泄漏检测,您需要在包含任何系统包含文件之前定义它。它只使用新的操作符检查泄漏,当然您必须重新编译代码,这样您就不能像valgrind那样附加它。

    请在此处查看更多信息:

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

        4
  •  0
  •   twk Mark Adler    16 年前

    我玩弄了一下Mike B指出的CRT调试堆函数,但最终我不满足于仅仅得到泄漏内存的地址。获得像umdh这样的堆栈可以使调试更快。所以,在我的main()函数中, 在运行测试之前和之后使用createprocess启动umdh以获取堆快照。我还编写了一个小的批处理文件,运行我的测试工具,然后对堆快照进行比较。因此,我启动了批处理文件,并获得了我的测试结果和一个文本文件,其中包含了所有未释放分配的完整堆栈。

    UMDH收集了很多误报,所以也许一些混合了crtdebug的东西和我现在所做的将会是一个更好的解决方案。但现在我对我所拥有的感到满意。

    现在,如果我有办法检测我是否没有关闭任何句柄…

        5
  •  0
  •   Lev    16 年前

    我做过一次,但不是那么自动的。我现在没有访问该代码的权限,但我的想法是:

    我用过 debug functions Mike B提到的(顺便说一句,它们只在调试中工作)。

    测试运行程序运行了所有测试两次,因为在第一次运行期间内存被分配给全局。第二次,在每次测试之前和之后检查分配的块的总数(我认为您可以在setup()和teardown()中进行检查)。如果数字不同,则表示内存泄漏,测试失败,并显示相应的消息。当然,如果测试本身失败,您应该保留它的错误消息。为了找到漏洞,我必须使用pblockheader读取上次分配的块分配号,然后使用 _CrtSetBreakAlloc 然后再跑。

    更多信息: http://levsblog.wordpress.com/2008/10/31/unit-testing-memory-leaks/