3

_CrtMemCheckpointWin32 /_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

2 番目のコード サンプルにより、boost::filesystem::path がいくつかの静的な内部状態を初期化していると言えます (これはプログラムの最後まで割り当てられたままです)。

単体テストでこのような問題を回避するにはどうすればよいですか?

最初のメモリ チェックポイントを取得する前に実行するテスト初期化メソッドを作成します。

理想的には、割り当てと割り当て解除をカスタマイズして追跡できるようにする必要があります (新規/削除のオーバーライド、カスタム アロケーターの追加など)。しかし、それはより難しく、使用するライブラリによっては許可されない場合があります。

テストを開始する前にそのような変数を初期化することは解決策ですか?

これは回避策です。あまりエレガントではありませんが、最終的には、知りたいことを伝えています。

他のコードを使用する場合、そのようなことをさらに多く行う必要がありますか?

使用しているライブラリとその柔軟性によって異なります。所有しているコードを完全にテストする場合は、内部でアロケーター型 (割り当てを追跡するためにカスタマイズできる std::allocator) を使用するか、new と delete をカスタマイズするか、複数の実装を提供できる割り当て API を作成することを検討する必要があります。

_CrtMem* Windows API に明示的に依存しないテスト コードを使用することもできます (boost::test ライブラリには、メモリ リークを検出するためのランタイム パラメーターがあるため、実際に自分で実装する必要はありませんが、それが何であるかはわかりません)。 Win64のフードの下でやっています。

于 2013-07-03T12:24:29.427 に答える