2

私は奇妙なクラッシュに遭遇しています。アプリケーション (VS2005 で開発された MFC ベース) のさまざまなモジュールを DLL に分離しようとしています。以下は、私がそれを達成しようとしている方法の骨格コードです:

一般的なヘッダー ファイル (base.h など) では:

class Base {
    vector<message> messages;
    ...
    ...
};

DLL ソース コード (class.h など) のヘッダー ファイル:

class Derived : public Base {
private:
    int hoo();
    ...
public:
    void foo();
    int goo();
    ...
};

extern "C" __declspec (dllexport) Derived* CreateDerived();

class.cpp で

 Derived* CreateDerived()
 {
    return new Derived;
 }

メインアプリケーションコードのファイル:

#include "base.h"
#include "class.h"

typedef Derived* (*DerivedCreator)();
...
...

void LoadDll()
{
    //DLL Load Code...
    ...
    ...

    DerivedCreator creator = reinterpret_cast<DerivedCreator>(::GetProcAddress(dllHandle, "CreateDerived"));

    Derived* pDerived = creator();

    pDerived->messages.push_back(message("xyz"));//Crashes here...
}

問題は、Base クラスのベクター メンバーにアクセスしようとした瞬間にコードがクラッシュすることです。これはリリース モードでのみ発生します。デバッグモードで問題なく動作します。リリース モードで Visual Studio から実行すると表示されるエラー メッセージは次のとおりです。

「Microsoft Visual Studio C ランタイム ライブラリは、Samsung SSD Magician.exe で致命的なエラーを検出しました。

Break を押してプログラムをデバッグするか、Continue を押してプログラムを終了してください。」

しかし、リリース バイナリを直接実行してデバッガをアタッチすると、アクセス違反が発生します。この時点で、デバッガーでベクターを確認すると、6 桁のエントリが表示され、どれも読み取り可能ではありません。Derived ポインターで Base クラスの残りのメンバーの正しい値を確認できます。

どんな助けでも大歓迎です。

4

1 に答える 1

2

DLL の境界を越えて stl コンテナーを渡すのは危険です。ここでの理由は、各モジュール (メイン アプリケーションと DLL) が独自のヒープ インスタンスを持っているためです。DLL のコンテキストで動的メモリを割り当てる場合、ポインタをアプリケーションに渡し、アプリケーションのコンテキストでそのメモリを解放すると、ヒープの破損が発生します。

それがまさにあなたの例で起こっていることです。

Derived* pDerived = creator();

CreateDerivedと呼ばれます。

 Derived* CreateDerived()
 {
    return new Derived;
 }

new DerivedDLL ヒープにメモリを割り当てます。

pDerived->messages.push_back(message("xyz"));

内部push_backでは、追加のメモリが に割り当てられBase::messages、その割り当てはアプリケーション ヒープで行われます。クラッシュ!

結論は、DLL 内でのみベクトルですべての操作を実行するには、DLL インターフェイスを再考する必要があるということです。

于 2012-04-20T11:22:28.210 に答える