0

次のような状況があります。

アンマネージ コードを呼び出して必要なことを行うサード パーティの .net ライブラリを使用しています (.net のものは単なる薄いラッパーです)。そのライブラリにはさまざまな IDisposable 実装などがありますが、それを usings でラップしていますが、それでもエラー、ふるいのようにメモリ リークが発生します (単体テストでこれを最終的に証明できました)。

もちろん、サードパーティにライブラリを修正してもらうのが理想的ですが、彼らは反応がなく、悲しいことに私もそれを削除することはできないので、私が現在行っていることはこれです...

このサード パーティ製ライブラリで行っている作業は、非常に簡単にカプセル化できるため、必要に応じて、いくつかのコマンド ライン引数を使用してプロセスを起動し、標準出力をキャプチャします。そのプロセスは必要なことを行い、結果オブジェクトを標準出力にシリアル化するだけで結果オブジェクトを返します。その後、プロセスを開始した起動アプリケーションのメソッドが結果オブジェクトを逆シリアル化し、何も異常がなかったかのように返します。

明らかに、これはすべて非常に厄介です (コマンドライン引数の解析、シリアル化などすべてが複雑になり、速度が低下します) が、非常にシンプルで機能するという利点があります (ありがたいことに、CreateNoWindow でウィンドウをオフにすることもできるため、ユーザーはアプリケーションも不都合なことには気付きません)。

私が考えた他のアプローチ:

  • アプリプールのアンロードなどですが、リークされたメモリは.netの外部に割り当てられているため、おそらく役に立たないと思いますか?
  • また、DLL をアンロードしようとしましたが、危険を伴うように見えます。これを安全かつ確実に実行できますか?

だから、私の質問は基本的に...

すべてを処理中のままにして、このサードパーティのライブラリの下部を何らかの方法でクリーンアップして、メモリをリークしないようにする方法はありますか?

4

1 に答える 1

1

...それはまだ、エラー、ふるいのようにメモリをリークします (単体テストでこれを最終的に証明することができました)。

答えは「いいえ」だと思いますが、尋ねなければなりません-通常の使用中にメモリを「リーク」する可能性はありますが、「シャットダウン」するとすべてをクリーンアップするのに十分賢いですか? 内部キャッシュが際限なく増加しているように見えるが、ライブラリの終了ルーチンが呼び出されるとクリーンアップされるライブラリを少なくともいくつか見つけました。

リークが本当に単なるバグであると仮定すると...

...必要な場所で、いくつかのコマンドライン引数を使用してプロセスを起動し、標準出力をキャプチャします

...状況のパラメーターを考えると、ここでのあなたのアプローチは最も合理的なものだと思います。実際には、「信頼」していないコードをホストしていることになります。これはおそらくセキュリティ上の理由ではなく、パフォーマンスや信頼性の理由によるものです。

アプリプールのアンロードなどですが、リークされたメモリは.netの外部に割り当てられているため、おそらく役に立たないと思いますか?

正解です -- それは役に立ちません。

また、DLL をアンロードしようとしましたが、危険を伴うように見えます。これを安全かつ確実に実行できますか?

それはおそらく問題を解決しません。あなたが言うようにコードにバグがある場合、アンロードされたときに割り当てられたリソースをクリーンアップすることはおそらくうまくいきません。(また、システムはそのリソースをクリーンアップすることもありません。リソースを解放せずに割り当てた場合、そのリソースは事実上リークします。)

この場合、他の方法でできることはほとんどありません。私が考えることができる唯一の最後の手段は、サードパーティのライブラリのルーチンをフック/インターセプトしようとすることです。何らかの方法で、すべての割り当てをプールに強制し、(ライブラリを解放した後に)一度にすべて解放することができます。しかし、あなたは本当にそれをしようとすべきではありません. それは非常に危険であり、ほぼ間違いなく努力する価値がない、正しく実装するのが難しすぎる、などです。

于 2012-07-09T09:09:22.590 に答える