同志adontzが正しく指摘したように、問題はCERを使用して解決されます。
CERはConstrained Execution Regionテクノロジーであり、その一部でStackOverflowまたはThreadAbortタイプの非同期割り込みが発生すること、またはジッターが「落ちた」ことを保証することでコードを保護できます。一貫した状態の外部リソース。
トーゴ!
言い換えれば、ランタイムを「強制」してコードセクションをブロックし、実行のためにすべてを準備することができます。スタックとRAMに十分なメモリがあることを確認し、コードをjコード化してから破壊します! -準備されたコードを実行し、次に何かが起こったかどうかを把握します。
プロセスでコードの実行が「落ちる」ことを防ぐために、ランタイムはCER領域で実行できないことに対していくつかの制限を課します。 そして、一般的に、あなたが多くのことをすることができないように:
- MSIL-code newobjを実行します。
- ボクシングを実行します(既知のとおり、暗黙的にnewobjを呼び出します)(ボックス化解除-可能);
- 仮想メソッドを呼び出します(明らかに準備されていない場合-必要に応じて表示します)。
- Reflectionを介してメソッドを呼び出し、Transparent Proxiesを介してフィールドにアクセスします。
- シリアル化を使用する
- 多次元配列を使用してください(!);
だから、重い平日に私たちの
System.Runtime.CompilerServices.RuntimeHelpers
向かって掘り下げる必要があります。
私たちにとって最も重要なメソッドは
PrepareConstrainedRegions
であり、説明された準備を実行します。たとえば、_future_コールスタックを通過し、プレジットを実行し、ストップマークを配置します(仮想メソッドとインターフェイスを「額」に使用できない理由は明らかです)-動的なディスパッチがあり、実際のコードが実行されるまで呼び出しスタックを作成することは不可能です。 今から楽しい部分です。 このメソッドの使用は次のようになります。
... System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); try {} finally { // atomic- } ...
そうです-空のtryブロック、およびすべての中断されない操作はfinallyブロックに入れなければなりません!
チェックするには-このテスト:
Thread t = new Thread(new ThreadStart( () => { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { while (true) { } }})); t.Start(); Thread.Sleep(1000); t.Abort(); t.Join();
プログラムは機能し、終了しません。 try-finallyをコメントアウトすると、プログラムは終了します。 絶対-ThreadAbortException _not_のリクエストは、finallyブロックの終わりまで延期され(無限のwhile(true){}ループのために発生しません)、すぐに(ほぼすぐに)動作します
これで、IntPtrの例からコードを「修正」する方法がわかりました。
IntPtr ptr = IntPtr.Zero; try { //... System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { ptr = Marshal.AllocHGlobal(500); } // .., .. } finally { if( ptr != IntPtr.Zero ) Marshal.FreeHGlobal(ptr); } ...
将来のために-MSDNは、管理されていないリソースを避けることを推奨しています。 CLRを作成する目的の1つは、継承されたアンマネージコードとリソースと対話することであるという事実を踏まえると、やや奇妙なアドバイスです。
そのため、管理されていないリソースのある作業場所を慎重に確認することをお勧めします。これらの時点で完全に機能するプログラムでも、2〜3個の重大なバグを見つけることができることがわかります。
メモリリークの対処に役立つものだけを整理したことは明らかです。 しかし、CER自体については触れませんでした。CERに適したメソッドの契約、CER内で呼び出すためのイベントの準備、仮想メソッドの準備、クリティカルファイナライザー、FailFastおよびMemoryBarriersを使用して、プログラムの信頼できる操作を保証し、管理されていないリソースリークを防ぎます。 それについて書くか、MSDNに送信する必要がありますか?