6

A follow-up question to Memory leaks when calling ITK from Visual Studio DLL

I refined the problem to the simplest example.

struct A
  {
  public:
    A()
      {
      mp_data = new int(0x42);
      }
    ~A()
      {
      delete mp_data;
      }
    int* mp_data;
  };

A a;

When such a global class is defined in a DLL, Visual Studio debug CRT reports that mp_data is leaked on application shutdown. Does anybody know a workaround except disabling leak reporting?

4

5 に答える 5

5

_CrtDumpMemoryLeaks()メイン関数の最後で呼び出している場合、呼び出されたmp_data後に削除されるため、動作は予想さ_CrtDumpMemoryLeaks()れます。

_CrtDumpMemoryLeaks()これらのリークを見たくない場合は、静的オブジェクトの最後のデストラクタが呼び出された後(または、メモリが解放された後の最後のデストラクタで)呼び出す必要があります(非常に難しい作業です。それを試してみてください)。

よりクリーンなアプローチは、すべての静的オブジェクトを代わりにヒープに割り当て (の最初にmain)、最後にそれらの割り当てを解除することです。mainそうすれば、呼び出すことができ_CrtDumpMemoryLeaks()、メモリ リークが発生しなくなります。

参考までに、コンストラクタとデストラクタを持つ静的オブジェクトは、構築/破棄される順序が決定論的ではないため、とにかく悪いと見なされます。そのため、静的オブジェクトは、簡単にデバッグできないバグを引き起こすことがよくあります。

Andrey のコメントに関する編集: _CrtSetDbgFlagを呼び出してフラグの設定を解除すること_CrtDumpMemoryLeaksにより 、自動呼び出しを無効にすることができます。それが機能する場合は、デストラクタを呼び出す静的オブジェクトを追加できます。このオブジェクトが最後に破棄されるようにするには、#pragma init_seg(compiler) ディレクティブを使用できます。_CRTDBG_LEAK_CHECK_DF_CrtDumpMemoryLeaks()

これが機能するかどうかはわかりません...それ以外の場合、他のすべてのソリューションでは、おそらくITK ライブラリを変更する必要があります(これは可能なはずです。結局のところ、これはオープン ソース ライブラリなのでしょうか?!)。

于 2012-04-24T15:27:43.470 に答える
2

内部ライブラリを静的リンクからロード時動的リンクに移行する過程で同じ症状に遭遇し、私の場合の問題は、DLL プロジェクトと EXE プロジェクトが異なるバージョンの VC++ ランタイムにリンクされていることであることが判明しました。 /MFC ライブラリ (1 つは MBCS、もう 1 つは Unicode)。

私の場合、アプリケーションとライブラリは両方とも MFC を使用しており、CRT メモリ リーク ダンプをアクティブにする _AFX_DEBUG_STATE デストラクタは、2 つの個別のオブジェクトに対して 2 回呼び出されていました。DLL と EXE が異なるランタイム DLL にリンクされているため、ランタイムが効果的に複製されました。DLL の 1 つがリークをアンロードしてダンプするのが早すぎて、多数の誤ったリークが表示されます。両方のプロジェクトで同じ文字セットを使用するように切り替えると、個別のランタイム リンクが解決され、誤ったリーク レポートも解決されました。

私の場合、2 つの別個のランタイムへのリンクは意図的ではなく、とにかく他の問題を引き起こした可能性があります。これは明らかに、ライブラリがリンクされている CRT を制御できない、明確に定義された ABI を使用してサード パーティのライブラリを使用する場合には当てはまりません。

これがあなたのケースに当てはまるかどうかはわかりませんが、他の人に役立つ場合に備えて投稿したかった.

于 2014-02-05T18:23:46.887 に答える
2

次のいずれかで問題が解決します。

(1) MFC で DLL の偽の依存関係を作成する、または

(2) smerlin によって提案された解決策を使用します。このコードを DllMain の横に追加します。

struct _DEBUG_STATE
  {
  _DEBUG_STATE() {}
  ~_DEBUG_STATE() { _CrtDumpMemoryLeaks(); }
  };

#pragma init_seg(compiler)
_DEBUG_STATE ds;
于 2012-04-25T09:40:28.790 に答える
0

Visual Studio 2015 でも同じ問題がありました。すべての解決策を試しました。/MT偽の MFC 依存関係を使用した最初のソリューションは、Dll でコンパイラ オプションを選択した場合にのみ機能しました。したがって、DLL とメイン アプリケーションは同じヒープを共有しません。ただし/MD、DLL とメイン アプリケーション (Dll 境界) の間で STL コンテナーまたは文字列オブジェクトを共有する場合など、しばしば必要になります。/MDを使用すると、アプリと Dll は同じヒープを使用します。したがって、偽の MFC 依存関係を使用した最初の解決策はうまくいきませんでした。

メインアプリケーションでメモリリーク検出を無効にする2番目のソリューションは好きではありません。デストラクタでこの呼び出しを行う Dll が不要になった場合は、アプリケーションでメモリ リーク検出を再度有効にすることを忘れないでください。

別の解決策を見つけたので、偽のメモリリークはもうありませんでした。/delayloadDllのリンカー オプションを使用するだけで済みます。それで全部です :-)。コンパイラオプションでも機能しました/MD

ここでは、Dll 境界について何かを読むことができます (なぜ使用するの/MDですか?)。ここでは、一般的な CRT コンパイラ オプションに関する情報を読むことができます。

于 2016-12-23T13:31:38.060 に答える
0

MFC アプリケーションでは、次を呼び出して自動メモリ リーク ダンプを無効にすることができます。

AfxEnableMemoryLeakDump(FALSE);

これは、Visual Studio 2010 以降でサポートされています。ドキュメントについては、こちらを参照してください。

于 2015-08-24T15:31:37.043 に答える