14

別のC++DLLを使用するC#プラグインがあります。そのDLLへの唯一の参照は、プラグイン自体の中からです。親アプリケーションは、すべてのプラグインを独自のAppDomainにロードし、プラグインがアンロードされるときにこのAppDomainをアンロードします。

チェックしましたが、プラグインをアンロードすると、アプリケーションのメモリが確実に低下します。ロードされたすべての管理対象アセンブリを削除することもできます。問題は、ネイティブDLLを削除しようとすると、アプリケーション全体を閉じるまでアクセスが拒否され続けることです。

私はこれをしばらく見てきましたが、なぜこのDLLだけがメモリに残っているのか理解できません。

4

2 に答える 2

22

AppDomainsは、純粋なマネージコード構造です。そのようなものはネイティブコードには存在せず、Windowsはそれについて何も考えていません。したがって、ロードされたネイティブDLLのスコープはプロセスです。技術的には、pinvokeマーシャラーはDLLのカウントを参照し、どのAppDomainがDLLのロードをトリガーしたかを正確に追跡できます。ただし、そのDLLを使用するネイティブコードが実行されているかどうかはわかりません。別のAppDomainのコードから、場合によってはマーシャリングされたデリゲートを介して間接的に行われた呼び出しによって開始される可能性のあるネイティブコード。

AppDomainマネージャーがそのように使用されたDLLをアンロードすると、明らかに災害が発生します。これは厄介で、AccessViolationを診断することは不可能です。AppDomainがアンロードされた後、長時間トリガーされる可能性があるため、特に厄介です。

したがって、マーシャラーはそのようなカウントを実装せず、DLLはロードされたままになります。これが発生しないことを保証できるのはあなただけです。DLLで実行されるコードとその開始方法を正確に制御できます。DLLを強制的にアンロードできますが、ハックが必要です。LoadLibrary()を自分でPinvokeして、DLLへのハンドルを取得します。そして、FreeLibrary()を2回ピンボークして、強制的にアンロードします。WindowsもCLRも、あなたが不正行為をしていることを認識できません。この後、DLLを使用できないようにする必要があります。

于 2012-04-04T16:27:54.957 に答える
6

AFAIK(内部)ネイティブDLLは、Win32 APIを介してロードする必要があります...LoadLibraryプロセスメモリに直接ロードします-に固有ではない.NETアプリケーションの場合AppDomain... (これは純粋に.NET固有)...したがって、アンロードは必ずしもネイティブDLLをアンロードするわけではありません...LoadLibraryAppDomainAppDomain

この状況に関する興味深い議論:

それぞれのプラグインの実装を変更できる場合は、次のような問題を解決する「後期ネイティブバインディング」を実装します。

于 2012-04-04T16:03:30.223 に答える