私は、大きなファイルを処理するある仕事をデバッグしようとしています。コード自体は動作していますが、.NETランタイム自体から散発的なエラーが報告されています。文脈上、ここでの処理は、1.5GBのファイル(一度だけメモリにロードされる)を処理し、ループでリリースすることで、この別の予測不可能なエラーを再現しようとするものである。
私のテストの断片は、基本的に
try {
byte[] data =File.ReadAllBytes(path);
for(int i = 0 ; i < 500 ; i++)
{
ProcessTheData(data); // deserialize and validate
// force collection, for tidiness
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
}
} catch(Exception ex) {
Console.WriteLine(ex.Message);
// some more logging; StackTrace, recursive InnerException, etc
}
(いくつかのタイミングと他のものを含む)
ループは、非決定的な回数の繰り返しで、完全に成功し、何の問題もなく処理されます。例外ハンドラはヒットしない。このテストは多くのメモリを使用しますが、各反復の間に非常にうまく鋸歯状になっています(明らかなメモリリークはありませんし、ヘッドルームも十分にあります - 鋸歯状の最も悪い**ポイントで14GBの未使用の主記憶があります)。このプロセスは64ビットです。
Windowsのエラーログには3つの新しいエントリがあり、(終了コード80131506によって)実行エンジンエラー(厄介な小さな生き物)を示唆しています。関連する回答](https://stackoverflow.com/a/4367865/23354)は、GCエラーを示唆しており、同時実行GCを無効にするための"fix"がありますが、この"fix"は問題を防いでいません。
明確化:この低レベルのエラーは CurrentDomain.UnhandledException
イベントを発生させません。
Clarification: GC.Collect
は saw-toothing のメモリを監視し、メモリリークをチェックし、物事を予測可能にするためにのみ存在します。
さらにコンソールトレースを追加することで、それぞれの処理中にフォールトが発生することが確認されました。
foreach
しただけ) - 不思議なことに *検証中の GC "complete" の直後。というわけで、たくさんの異なるシナリオがあります。
クラッシュダンプ(dmp)ファイルを入手することができます。
ツール->デバッグ->一般->.Net Frameworkのデバッグを有効にする`を選択します。
ツール->IntelliTace->IntelliTaceEbentsとコールインフォメーション`。
ツール->IntelliTace-> StorIntelliTaceレコードをこのディレクトリに設定する `
と入力し、ディレクトリを選択します。
を選択すると、.netのコードに入り、すべての関数コールをトレースすることができます。 小さなサンプルプロジェクトで試してみましたが、うまくいきました。
各デバッグセッションの後、それはデバッグセッションの記録を作成することを仮定します。 もし私が間違っていなければ、CLRが死んだとしても。
これによって、CLRが崩壊する前に正確なコールに到達することができるはずです。
一般的な例外ハンドラを書いてみて、処理されない例外があなたのアプリを殺していないかどうか見てみてください。
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler);
static void MyExceptionHandler(object sender, UnhandledExceptionEventArgs e) {
Console.WriteLine(e.ExceptionObject.ToString());
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
Environment.Exit(1);