none
DLLで[共有 DLL で MFC を使う]とメモリリーク RRS feed

  • 質問

  • DLLで[共有 DLL で MFC を使う]とメモリリーク

    いつもお世話になります。また、よろしくです。

    DLL側(EXEからロードされる)の構成プロパティ
     MFCの使用:[共有 DLL で MFC を使う]
     文字セット:[マルチ バイト文字セットを使用する]

    EXE側(DLLをロードする)の構成プロパティ
     文字セット:[Unicode 文字セットを使用する]

    上記状況で、DLLをロードするEXEをデバッグすると、EXEの終了後、[出力元の表示]欄にメモリリークが発生したというメッセージがでます


    メモリリークの例示(抜粋):
    Detected memory leaks!
    f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(173) : {726} normal block at 0x0032F430, 114 bytes long.
    f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {238} normal block at 0x00327D58, 28 bytes long

    DLLにおいてMFCの使用を[スタティック ライブラリで MFC を使用する]とメモリリークは発生しなくなります。
    [スタティック ライブラリで MFC を使用する]ってのが正しい対処方法なのでしょうか?
    それとも何か他に正しい対処方法があるのでしょうか?

    kinzi815さんが「マルチ バイト文字セット環境でのUnicode文字列の扱い」の2008年12月10日の投稿で似たエラーを出しています。
    が、まだ未解決のようです。

    OS:Windows Vista
    Visual Studio 2008 Standard Edition
    言語:Visual C++
    Microsoft Visual C++ 2008 SP1 :導入済み
    Microsoft Visual C++ 2008 SP1 再頒布可能パッケージ (x86):導入済み

    2009年7月10日 22:24

回答

  • これのことでは?
    http://support.microsoft.com/kb/167929/en-us

    メモリリークではないけれども、構造上メモリリーク検出機構に引っかかるようなイメージでしょうか。
    (MFC-ANSIのDLLをUnloadするときにこれまでに確保した領域を解放し忘れていないかとチェックするが、この後に解放処理が行われる予定のMFC-UnicodeのEXE部分でのメモリが残っているため、誤ってメモリリークと検出される?)
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月11日 14:40
    モデレータ

すべての返信

  • これのことでは?
    http://support.microsoft.com/kb/167929/en-us

    メモリリークではないけれども、構造上メモリリーク検出機構に引っかかるようなイメージでしょうか。
    (MFC-ANSIのDLLをUnloadするときにこれまでに確保した領域を解放し忘れていないかとチェックするが、この後に解放処理が行われる予定のMFC-UnicodeのEXE部分でのメモリが残っているため、誤ってメモリリークと検出される?)
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年7月11日 14:40
    モデレータ
  • お見事!

    ご紹介頂いたサイトの情報を読みました。

    私が体験したメモリリークは偽物だったんですね。その偽物は無視して良いとのことです。
    原因が判明し、ありがたいです。
    貴重な情報提供をして頂き、ありがとうございました。

    TRACE(_T("ExitInstance() for regular xxx: xxxx. \n"));ってのを、
    DLLとEXEの両方の
    int CxxxxApp::ExitInstance()関数の中に書いてやるのが「解決策」だそうです。

    「解決策」に基づく表示結果例示:
    ExitInstance() for regular EXE: xxxx.EXE  (これが目印)
    ExitInstance() for regular DLL: xxxxDLL  (これが目印)
    Detected memory leaks!
    Dumping objects ->
    f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(173) : {726} normal block at 0x00DCF430, 114 bytes long.
    (以下省略)

    偽のメモリリークのメッセージは表示されてしまいます。なので「目印」を付けるって程度の解決策です。

    CWinApp::ExitInstance() の実行後に出てくるメモリリークが真のメモリリークだそうです。
    「目印」の後で、CWinApp::ExitInstance()が実行されます。(それじゃあ、メモリリークの真偽が分らんのじゃないか)

    偽のメモリリークのメッセージの後に、「DLLのアンロード」の表示がされます。
    「DLLのアンロード」の後に、EXE及びDLLの両方の真のメモリリークのメッセージがでます。(自分で実験して確認した)

    「DLLのアンロード」の後に出てくるメモリリークのメッセージが真実なので、それを見ろってのが真の解決策であるように感じる。
    TRACEを書く意味が無いような気がする。

    2009年7月12日 13:39
  • 先程の私の書きこみに誤りがありました。

    FreeLibrary()は任意の時点で実行できるので、
    「「DLLのアンロード」の後に出てくるメモリリークのメッセージが真実」
    ってのは一般論では言えません。

    私が開発しているプログラムはデストラクタでFreeLibrary()をやってたので、
    私の場合だけ言える事柄です。

    間違えてすいませんでした。

    2009年7月13日 4:15