4

今日このバグが発生しました。これは、を呼び出した後にDLL内から割り当てられた文字列を使用していることが原因であることが判明しましたFreeLibrary()

これは、クラッシュを再現する簡単な例です。これはDLLになります:

void dllFunc(char **output)
{
    *output = strdup("Hello"); // strdup uses malloc
}

これは、DLLをロードするEXEにあります。

void exeFunc()
{
    char *output;
    dllFunc(&output);
    std::string s1 = output; // This succeeds.
    FreeLibrary(dll);
    std::string s2 = output; // This crashes with access violation.
}

のドキュメントを読みましたが、FreeLibrary()呼び出された後にメモリが無効になることについては何も見つかりませんでした。

編集

EXEにVS2010ツールチェーンを使用しているときにDLLにVS2008ツールチェーンを使用していたことに気付きました(両方のIDEとしてVS2010を使用していましたが、プロジェクト設定からツールチェーンを選択できます)。DLLのツールチェーンをVS2010に設定すると、クラッシュも解消されました。

4

2 に答える 2

7

MSVCRT(Cランタイム)ライブラリとの静的リンクを選択すると、説明した動作が得られます。EXEとDLLがMSVCRTDLLに動的にリンクされているが、異なるバージョンを使用している場合にも、同じことが起こります。または、同じバージョンと一致しているが、一方がDEBUGを使用していて、もう一方がRETAILを使用している場合。つまり、メモリは、割り当てに使用されたMSVCRTxxx.dllの存続期間と同じくらい良好です。私はあなたの質問に対するあなたの更新を見たばかりです-はい、VS2008と2010の間でCRTを混合して一致させることがクラッシュの正確な理由です。

DLLとEXEの両方がMSVCRTDLLの同じバージョンに動的にリンクされている場合は、メモリヒープを共有し、発生している問題を回避します。

標準的な方法は次のとおりです。エクスポートされたDLL関数が、後で「解放」または「解放」する必要があるものを返す場合、標準的な方法は、割り当て解除を処理するためにDLLからエクスポートされた追加の関数を提供することです。

プロジェクトのC/C ++プロジェクト設定のコード生成ページから、EXEとDLLの両方のCランタイムリンケージを構成できます。

ここの写真:http://imgur.com/uld4KYF.png

于 2013-03-09T06:57:25.493 に答える
5

これは、各DLLが独自のメモリヒープ(mallocおよびそのCフレンド、およびnew内部で、通常はを介して使用するHeapAlloc)を作成し、DLLが解放されると、そのヒープも作成されるために発生します。

Dllメモリに関するその他の警告については、このMSDNの記事を参照してください。すべてのバイナリで共有されるカスタムメモリアロケータを使用している場合を除き、動的に割り当てられたメモリを、それを作成したモジュール内に保持する必要があります(オブジェクトがその作成者よりも長持ちしないことを100%保証できない場合)。

于 2013-03-08T18:36:20.787 に答える