none
「スタティックライブラリでMFCを使用する」を選択してビルドしたexeが実行時にエラー RRS feed

  • 質問

  • お世話になります。

    開発環境:VS2008

    開発物
        A.exe(MFC使用)
        B.dll(MFC不使用)
            B.dllをlibを使って明示的にリンクしています。

    A.exeのプロジェクトのプロパティにて、MFCの使用を「スタティックライブラリでMFCを使用する」にしてビルドをすると、
    ビルド自体は成功するのですが、実行時にエラーが発生します。
    呼び出し履歴を見ると、B.dll内で宣言しているクラスのオブジェクトをdeleteした際、デストラクタの処理を抜けた直後にエラーが発生していました。

    B.dllのバグかと思ったのですが、A.exeのプロジェクトのプロパティにてMFCの使用を「共有DLLでMFCを使う」に設定するとこのエラーは発生しないため、
    どこに原因があるのか分からずに混乱しています。

    下記がエラー発生時の状況になります。

    ■プロジェクトの設定

    A.exeのプロジェクト設定
        構成の種類    :アプリケーション
        MFCの使用    :スタティックライブラリでMFCを使用する
        ランタイムライブラリ:マルチスレッド(/MT)
       
    B.dllのプロジェクト設定
        構成の種類    :ダイナミックライブラリ
        MFCの使用    :標準Windowsライブラリを使用する
        ランタイムライブラリ:マルチスレッド(/MT)
       
    ■エラー発生時の呼び出し履歴

    >    A.exe!_CrtIsValidHeapPointer(const void * pUserData=0x020d2ba0)  行 2103    C++
         A.exe!_free_dbg_nolock(void * pUserData=0x020d2ba0, int nBlockUse=1)  行 1317 + 0x9 バイト    C++
         A.exe!_free_dbg(void * pUserData=0x020d2ba0, int nBlockUse=1)  行 1258 + 0xd バイト    C++
         A.exe!operator delete(void * p=0x020d2ba0)  行 373 + 0xb バイト    C++
         A.exe!CData::`scalar deleting destructor'()  + 0x3c バイト    C++

    ■Dependency Walkerの解析結果
        A.EXE
            SHELL32.EXE
                SHDOWVW.DLL
                    MSHTML.DLL
                        (?)MSJAVA.DLL
        MSJAVA.DLL error opening file 指定されたファイルが見つかりません(2)


    このエラーについて、何かご存知の方がいらっしゃいましたらご助言をお願い致します。
    MSDN
    2011年4月20日 4:29

回答

  • B.dllで作成したオブジェクトをA.exeでdeleteしていたりしませんか?

    ランタイムライブラリがメモリ管理を行っていて、両者が同一のDLLを使用していればいいのですが、B.DLLはDLLバージョンを使用しますが、A.EXEはスタティックバージョンを使用しているため、管理領域が違ってきていると思います。

    解決策としては、B.DLLで作成したオブジェクトはB.DLL内で開放するようにしましょう。

    • 回答としてマーク 山本春海 2011年5月9日 5:56
    2011年4月20日 5:33
  • 共有 DLL を使用するとスタティックリンクを使用するの設定を切り換える(変更して適用する)と、C++ - コード生成にあるランタイム ライブラリの設定も連動して変わります。
    共有 DLL を使用する場合は /MD、スタティックリンクを使用する場合は /MT になるはずです。

    ちなみに、B.dll は本当に /MT なんでしょうか?
    共有 DLL を使用する場合、つまり、/MD の場合はうまく動くのであれば、B.dll も /MD になっていそうな気がしたので。

    結論は、B.DLL で作ったオブジェクトは B.DLL で解放するという話で同意見です。
    (最悪、Release メンバー関数でも作ってください)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年4月20日 13:54
    モデレータ

すべての返信

  • B.dllで作成したオブジェクトをA.exeでdeleteしていたりしませんか?

    ランタイムライブラリがメモリ管理を行っていて、両者が同一のDLLを使用していればいいのですが、B.DLLはDLLバージョンを使用しますが、A.EXEはスタティックバージョンを使用しているため、管理領域が違ってきていると思います。

    解決策としては、B.DLLで作成したオブジェクトはB.DLL内で開放するようにしましょう。

    • 回答としてマーク 山本春海 2011年5月9日 5:56
    2011年4月20日 5:33
  • 共有 DLL を使用するとスタティックリンクを使用するの設定を切り換える(変更して適用する)と、C++ - コード生成にあるランタイム ライブラリの設定も連動して変わります。
    共有 DLL を使用する場合は /MD、スタティックリンクを使用する場合は /MT になるはずです。

    ちなみに、B.dll は本当に /MT なんでしょうか?
    共有 DLL を使用する場合、つまり、/MD の場合はうまく動くのであれば、B.dll も /MD になっていそうな気がしたので。

    結論は、B.DLL で作ったオブジェクトは B.DLL で解放するという話で同意見です。
    (最悪、Release メンバー関数でも作ってください)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年4月20日 13:54
    モデレータ
  • 細かいことなのですが

    /MTと/MTd ではなく、 /MTと/MD ではないでしょうか

    2011年4月22日 0:05
  • 細かいことなのですが

    /MTと/MTd ではなく、 /MTと/MD ではないでしょうか


    ぼけてたようなので直しておきました。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年4月22日 14:57
    モデレータ