0

リッチエディットコントロールの使用によると、私はリッチエディットを次のように使用しています。

MyControl::OnCreate()
{
    handle = LoadLibrary(_T("Riched20.dll"));
}

MyControl::OnDestroy()
{
    FreeLibrary(handle);
}

win32では正常に動作しますが、最近x64構成を構築したため、ページのリロード後にコントロールが失敗します。

代替テキスト

これを行うと、次のことに気づきました。

MyControl::OnCreate()
{
    handle = LoadLibrary(_T("Riched20.dll"));
    FreeLibrary(handle);
    handle = LoadLibrary(_T("Riched20.dll"));
}

すべてが正常に動作します。

このコードを本番環境に移行したくないので、より良い解決策/回避策について何か提案はありますか?

4

1 に答える 1

3

報告された障害モジュールはRichedit20.dll_unloadedであるため、DLLからのコードがまだ使用されている間にDLLをアンロードしていることを意味します。

たとえば、DLLを(完全に)解放したときにまだリッチエディットウィンドウを開いている場合は、何かがコントロールのwindow-procの呼び出しをトリガーするとすぐに、そのようなクラッシュが発生する可能性があります。これは、コントロールのwindow-procがアンロードされたDLLコード内にあったためです。

LoadLibraryとFreeLibraryを複数回呼び出すのは安全なはずです(呼び出しのバランスが取れている限り)ので、それが問題であるとは思えません。問題を引き起こしているだけかもしれません。また、問題は32ビットビルドにありました。あなたは幸運に恵まれ、それを引き起こしたことはありません。

OnDestroyは、FreeLibraryを呼び出すのに間違った場所です。WM_DESTROYの後にウィンドウに送信されるウィンドウメッセージがいくつかあります(例:WM_NCDESTROY)。

OnDestroyが呼び出されても、子ウィンドウは引き続き存在します。リッチエディットが(コントロール自体ではなく)コントロールの子である場合、FreeLibraryをOnNcDestroyに移動すると節約できる場合があります。(子ウィンドウは、WM_NCDESTROYが呼び出されるまでに破棄されます。)ただし、ライブラリを解放するのに適した場所ではないと思います。

したがって、FreeLibrary呼び出しを確実に移動する必要があります。それとLoadLibraryの両方を完全にコントロールから外します。ライブラリのインスタンスが作成されるたびにライブラリをロード/解放するコントロールがあるのは通常ではありません。代わりに、静的なinit / uninitコードをどこかに置いて、必要なライブラリを一度だけロードし、アプリケーションのシャットダウン時にそれらを解放します。

(アプリがコントロールをほとんど使用しない場合は、コントロールを使用するウィンドウがアクティブな場合にのみライブラリをロード/解放することが理にかなっている場合があります。ただし、そのような状況はまれです。通常は、DLLをロードしたままにしておくことをお勧めします。)

于 2010-11-22T06:33:32.967 に答える