3

C#コードにストレスをかけ、メモリ不足の状態で実行したときに発生するクラッシュを追跡しようとしています。ただし、場合によっては、OutOfMemoryExceptionを取得する代わりに、プログラムがクラッシュして終了することがあります。これは通常、バッファのオーバーランによるメモリの破損、またはスタックオーバーフロー(または破損)が原因で発生します。

それで、ヒープの整合性をチェックする方法はありますか、それともスレッドに残っているスタックの量をチェックする方法はありますか?

速度の理由で安全でないコードをたくさん使用しているので、どこかにコードが破損している可能性があります。残念ながら、破損が発生した後、クラッシュはランダムな間隔で発生します。C#がバッファオーバーランを検出するとアプリを閉じることは理解していますが、強制的にチェックを行う方法はありますか?

ありがとう。

4

3 に答える 3

3

制約付き実行領域を使用して、これらの状況を処理できます。

制約付き実行領域(CER)は、信頼性の高いマネージコードを作成するためのメカニズムの一部です。CERは、共通言語ランタイム(CLR)が帯域外例外をスローしないように制約されている領域を定義します。これにより、領域内のコードが完全に実行されなくなります。その領域内では、ユーザーコードは、帯域外例外をスローする結果となるコードの実行を制限されます。メソッドは、ブロックのPrepareConstrainedRegions直前にあり、、、およびをtryマークする必要がありますcatchfinallyfault制約された実行領域としてブロックします。制約付き領域としてマークされると、コードは強力な信頼性契約を持つ他のコードのみを呼び出す必要があり、コードが障害を処理する準備ができていない限り、コードは準備されていないメソッドまたは信頼性の低いメソッドに仮想呼び出しを割り当てたり、呼び出したりしないでください。CLRは、CERで実行されているコードのスレッドアボートを遅延させます。

もちろん、CERは非常に制限的です。あなたはそれらで多くをすることはできません。これらは、コードの重要な小さな部分のために設計されています。

于 2009-10-28T15:28:37.023 に答える
2

問題を追跡しようとしているときに、次の記事が非常に役立つことがわかりました。

メモリの問題の調査

メモリが不足している場合…</a>

IGCHost インターフェイス

制御することで .NET を最大限に活用する

最後の記事には次のように書かれています。

例外オブジェクトにメモリを割り当てることができない場合、例外ハンドラーに実行の機会を与えることなくランタイムが終了します。これは、望ましい動作になることはめったにありません。[そのため] 単純に追加のメモリの割り当てを拒否するのではなく、より穏やかで効果的な手法は、わずかなメモリの増加を許可して、例外オブジェクトを正常に作成し、OutOfMemory 例外をマネージ コードによって適切にスローして処理できるようにすることです。

これが私の問題を回避するために必要なことだと思います。私のアプリは非常にメモリを集中的に使用するため、ページング ファイルにメモリを破棄する余裕はありません。非常に遅いためです。許容できるパフォーマンスを維持するために、アプリ自体を物理メモリに制限する必要があります。しかし、メモリが不足した場合は、メモリ不足の例外を発生させる必要があります。アプリを単純にクラッシュさせることはできません!

そのため、その記事に記載されている手法を実装して、問題が解決するかどうかを確認します。残念ながら、少し複雑なので、すぐに試すことはできません。

于 2009-10-28T22:48:57.680 に答える
1

OS がプロセスを消去せざるを得ない特定の条件があります。プロセスでスタック オーバーフローやセグメント フォールトなどの例外を発生させるには、カーネルがプロセスに制御を戻す前に、フォールトが発生しているスタックに EXCEPTION_RECORD を書き込む必要があります。このレコードを書き込む余地がない場合、プロセスは消滅するだけであり、それを止めるためにできることは何もありません。これが発生する可能性があることを私が知っている 2 つの状況は、EXCEPTION_STACK_OVERFLOW の後にスタックを拡大し続ける場合と、予約されたスタック ページをコミットできない場合です。どちらも非常にまれな状況です。

あなたの最善の策は、破損を修正することです。gflags PageHeap保護の下で実行してみてください。例外が発生する場所がわかっている場合は、デバッガーでバッファーにブレーク オン ライト ブレーク ポイントを設定してみてください。または、書き込みパターン (たとえば、文字列など) から、またはメモリを検索してバッファへの参照を探して、scribbler 事後分析を特定してみてください。

于 2009-10-28T15:46:17.563 に答える