3

我们有几个单元测试使用 Win32 _CrtMemCheckpoint/_CrtMemDifference方法来检测被测代码中的内存泄漏。在 x64 机器(Windows 7)上,其中一些测试报告了 x86(32 位)机器上未报告的内存泄漏。在这些 x64 机器上,使用 VS2008 或 VS2012 并使用 Boost 1.52.0 编译以下代码,结果是“检测到内存泄漏!”:

#include <boost/filesystem.hpp>
#include <crtdbg.h>

int main(int argc, char **argv) 
{
    _CrtMemState state1, state2, state3;
    _CrtMemCheckpoint(&state1);

    {
        boost::filesystem::path remoteDirPath("c:/");
    }

    _CrtMemCheckpoint(&state2);

    int res = _CrtMemDifference( &state3, &state1, &state2);
    if (res != 0)
    {
        _CrtDumpMemoryLeaks();  
        std::cout << "Memory leak detected!";
    }
}

这实际上是 boost::filesystem::path 中的内存泄漏吗?我想这是一些库初始化左右,因为

int main(int argc, char **argv) 
{
    {
        boost::filesystem::path initDummy("c:/");
    }
    _CrtMemState state1, state2, state3;
    _CrtMemCheckpoint(&state1);

    {
        boost::filesystem::path remoteDirPath("c:/");
    }

    _CrtMemCheckpoint(&state2);

    int res = _CrtMemDifference( &state3, &state1, &state2);
    if (res != 0)
    {
        _CrtDumpMemoryLeaks();  
        std::cout << "Memory leak detected!";
    }
}

不输出“检测到内存泄漏!”。

我的问题是:如何避免单元测试出现此类问题?在开始测试之前初始化这样一个变量是一个解决方案吗?使用其他代码时,我是否需要做更多这样的事情?还是一般来说做这样的测试是个坏主意?

谢谢你的想法!

4

1 回答 1

1

由于您的第二个代码示例,我会说 boost::filesystem::path 正在初始化一些静态内部状态(它一直分配到您的程序结束)。

如何避免单元测试出现此类问题?

创建一个在获取第一个内存检查点之前执行的测试初始化​​方法。

理想情况下,您应该能够自定义分配和取消分配以进行跟踪(覆盖新/删除,添加自定义分配器等),但这更困难并且可能不允许这样做,具体取决于您使用的库。

在开始测试之前初始化这样一个变量是一个解决方案吗?

这是一种解决方法。不是很优雅,但最后,它告诉你你想知道什么。

使用其他代码时,我是否需要做更多这样的事情?

取决于您使用的库以及它们的灵活性。如果您正在测试您完全拥有的代码,您应该考虑在内部使用分配器类型(您可以自定义以跟踪分配的 std::allocator)、自定义 new 和 delete 或编写一些您可以为其提供多个实现的分配 API。

您还可以使用不明确依赖 _CrtMem* Windows API 的测试代码(boost::test 库有一个运行时参数来检测内存泄漏,因此您不必自己实际实现它,但我不知道它是什么在 Win64 的引擎盖下做。

于 2013-07-03T12:24:29.427 回答