9

標準のユーティリティを使用して、アプリケーションのメモリリークを見つけたい。以前は自分のメモリアロケータを使用していましたが、他の人(そう、AlienFluid)がMicrosoftのApplication Verifierの使用を提案しましたが、リークを報告することができないようです。私は次の簡単なアプリケーションを持っています:

#include <iostream>
#include <conio.h>

class X
   {
   public:
      X::X() : m_value(123) {}
   private:
      int m_value;
   };

void main()
{
X *p1 = 0;
X *p2 = 0;
X *p3 = 0;

p1 = new X();
p2 = new X();
p3 = new X();
delete p1;
delete p3;
}

このテストには明らかにメモリリークが含まれています。p2は新規ですが削除されていません。

次のコマンドラインを使用して実行可能ファイルをビルドします。

cl /c /EHsc /Zi /Od /MDd test.cpp
link /debug test.obj

Application Verifier(4.0.0665)をダウンロードし、すべてのチェックを有効にしました。

テストアプリケーションを実行すると、Application Verifierでそのログを確認できますが、メモリリークは発生しません。

質問:

  • Application Verifierがリークを報告しないのはなぜですか?
  • それとも、Application Verifierは本当にリークを見つけることを目的としていませんか?
  • アプリケーションの最後にリークを明確に報告するために利用できる他のツールがない場合(つまり、1 GB以上のアプリケーションでは不可能であるため、定期的なスナップショットを作成して比較することはできません)。割り当て場所(CRTの最後の単純なリークレポートではありません)

適切なユーティリティが見つからない場合でも、自分のメモリマネージャに依存する必要があります(これは完全に機能します)。

4

7 に答える 7

4

CRTメモリリークの検出(スタックトレースなし):

// debug_new.h
#pragma once

#include "crtdbg.h"

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK、__FILE__、__LINE__)
#endif
#endif

すべての.cppファイル:

#include "debug_new.h"

..。

//他のすべてのインクルード行の後:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

..。

これをプログラム初期化コードに1回記述します。

_CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

MFCでは、これはすべてMFCヘッダーにすでに実装されています。すべてのcppファイルに次の行が含まれていることを確認する必要があります。

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

制限事項:これは「新しい」メモリリークのみをキャッチし、mallocなどの別の関数によって引き起こされたすべてのリークはキャッチされません。

.hファイル内で割り当てを行わないでください。DEBUG_NEWはすべての#include行の後に定義されているため、ソース行なしで出力されます。

于 2010-06-02T09:05:10.260 に答える
4

Application Verifierは、DLLのリークのみをキャッチします。リークチェックボックスのツールチップを読んでみてください。それはそれが言うことです。

于 2011-05-04T02:32:58.013 に答える
1

Application Verifierは、出口パスを特殊なケースとして扱い、これらにリークのフラグを立てないように感じます。結局のところ、プロセスヒープ全体は、プロセスの終了時に解放されます。

同じポインタを再度初期化する別のサンプルを作成してみてください。基本的に、前の割り当てへの参照は失われます。それは確かにフラグを立てるべきです。結果を教えてください。

また、AppVerifier(すべてのオプションを有効にしている場合)は、バッファオーバーフロー、アンダーフロー、ROとマークされたスタック位置への書き込みなどもキャッチする必要があります。

于 2010-06-04T00:04:22.640 に答える
1

SoftwareVerificationのMemoryValidatorは、メモリリークをキャッチし、リークの割り当てから完全なコールスタックを表示します。商用製品ですが、試用期間があるため、プログラマーは試してみて、価格に見合う価値があるかどうかを確認できます。

于 2012-06-18T16:33:28.243 に答える
0

最も簡単な解決策は、最初にリークやバッファオーバーフローを書き込まないことです。イベント後にそれらを検出することは、実際には労力の無駄です。私自身のコードでは、何年もの間、これらの領域で問題は発生していません。なんで?なぜなら、私はC++が提供するメカニズムを使用してそれらを回避しているからです。例えば:

X *p1 = 0;
p1 = new X();

する必要があります:

shared_ptr <X>  p1 = new X();

そして、p1のリークについてもう心配する必要はありません。さらに良いことに、動的割り当てはまったく使用しないでください。

X x1;

バッファオーバーフローの場合は、入力時に大きくなるstd :: stringのようなタイプを常に使用します。または、大きくならない場合は、オーバーフローの可能性を検出して警告します。

私はメモリリークを回避する能力を自慢していません-これは実際に機能し、コードのビジネスロジックをデバッグするというはるかに難しいタスクに取り掛かることができます。

于 2010-06-02T09:14:48.240 に答える
0

Visual Leak Detector(v2.2)は、メモリ割り当てに使用された完全なコールスタックがリークにつながったことを示すため、CRTデバッグライブラリよりも便利です。

于 2011-10-28T17:15:14.820 に答える
0

Application Verifierはこのジョブに適したツールではありませんが、ApplicationVerifierチェックを有効にすることをお勧めします。Windowsで同等のUMDH(ユーザーモードダンプヒープ)です。

私の元同僚は、少なくともある程度のユーザビリティのためにUMDHGuiを作成しました。

于 2022-01-13T12:16:25.773 に答える