68

大きなファイルを処理するいくつかの作業をデバッグしようとしています。コード自体は機能しますが、.NETランタイム自体から散発的なエラーが報告されています。コンテキストとして、ここでの処理は1.5GBのファイル(メモリに1回だけロードされる)であり、ループで処理および解放されます。これは、この他の方法では予測できないエラーを意図的に再現しようとするためです。

私のテストフラグメントは基本的に次のとおりです。

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を介して)実行エンジンエラー(厄介な小さな生き物)を示唆しています。関連する回答は、並行GCを無効にする「修正」を伴うGCエラーを示唆しています。ただし、この「修正」によって問題が防止されるわけではありません。

明確化:この低レベルのエラーはCurrentDomain.UnhandledExceptionイベントに影響しません。

明確化:GC.Collect鋸歯状のメモリを監視し、メモリリークをチェックし、物事を予測可能に保つためだけにあります。それを削除しても問題は解決しません。反復間でより多くのメモリを保持し、dmpファイルを大きくします; p

さらにコンソールトレースを追加することで、次のそれぞれの間に障害が発生することを確認しました。

  • デシリアライズ中(多くの割り当てなど)
  • GC中(GC通知APIを使用したGC「アプローチ」とGC「完了」の間)
  • 検証中(foreach一部のデータのすぐ上)-不思議なことに、検証中のGCが「完了」した直後

さまざまなシナリオがたくさんあります。

クラッシュダンプ(dmp)ファイルを取得できます。これをさらに調査して、システムが非常に見事に失敗したときにシステムが何をしているかを確認するにはどうすればよいですか?

4

5 に答える 5

23

メモリダンプがある場合は、WinDbgを使用してそれらを確認することをお勧めします。ただし、まだ行っていないことを前提としています。

コメント!EEStack(ネイティブスタックトレースとマネージドスタックトレースの混合)を実行して、スタックトレースに飛び出す可能性のあるものがあるかどうかを確認します。私のテストプログラムでは、FEEEが発生したスタックトレースとしてこれを見つけました(意図的にヒープを破壊していました):

0:000>!EEStack
---------------------------------------------
スレッド0
現在のフレーム:ntdll!NtWaitForSingleObject + 0xa
子-SPRetAddr呼び出し元、呼び出し先
00000089879bd3d0 000007fc586610ea KERNELBASE!WaitForSingleObjectEx + 0x92、ntdll!NtWaitForSingleObjectを呼び出します
00000089879bd400 000007fc5869811c KERNELBASE!RaiseException + 0x68、ntdll!RtlRaiseExceptionを呼び出します
[...]
00000089879bec80 000007fc49109cf6 clr!WKS :: gc_heap :: gc1 + 0x96、clr!WKS :: gc_heap::mark_phaseを呼び出します
00000089879becd0 000007fc49109c21 clr!WKS :: gc_heap :: garbage_collect + 0x222、clr!WKS :: gc_heap::gc1を呼び出します
00000089879bed10 000007fc491092f1 clr!WKS :: GCHeap :: ResetEE + 0xa2、clr!Thread::ResumeRuntimeを呼び出します
00000089879bed60 000007fc4910998d clr!WKS :: GCHeap :: GarbageCollectGeneration + 0xdd、clr!WKS :: gc_heap::garbage_collectを呼び出します
00000089879bedb0 000007fc4910df9c clr!WKS :: GCHeap :: Alloc + 0x31b、clr!WKS :: GCHeap::GarbageCollectGenerationを呼び出します
00000089879bee00 000007fc48ff82e1 clr!JIT_NewArr1 + 0x481

これはガベージコレクタからのヒープの破損に関連している可能性があるため、!VerifyHeapコマンドを試してみます。少なくとも、ヒープが無傷である(そして問題が他の場所にある)ことを確認するか、問題が実際にGCまたは一部のP/Invokeルーチンで破損している可能性があることを発見できます。

ヒープが破損していることがわかった場合は、ヒープのどれだけが破損しているかを調べてみてください。これは、を介して実行できる可能性があります!HeapStat。ただし、特定の時点からヒープ全体が破損していることを示しているだけかもしれません。

WinDbgを介してこれを分析する他の方法を提案することは困難です。なぜなら、コードが何をしているのか、またはコードがどのように構造化されているのかについての本当の手がかりがないからです。

ヒープの問題であり、GCの奇妙さの可能性があることを意味する場合は、WindowsのイベントトレースでCLRGCイベントを確認します。


取得しているミニダンプがそれをカットしておらず、Windows 7 / 2008R2以降を使用している場合は、グローバルフラグ(gflags.exe)を使用して、プロセスが例外なく終了したときにデバッガーをアタッチできます。 WER通知を受け取らない。

Silent Process Exitタブに、実行可能ファイルへのフルパスではなく、実行可能ファイルの名前を入力します(例:) TestProgram.exe。次の設定を使用します。

  • [サイレントプロセス終了監視を有効にする]をオンにします
  • モニターの起動プロセスを確認する
  • 監視プロセスには、を使用します {path to debugging tools}\cdb.exe -server tcp:port=5005 -g -G -p %e

そして、設定を適用します。

テストプログラムがクラッシュすると、cdbが接続され、接続するのを待ちます。WinDbgを起動し、Ctrl + Rと入力して、接続文字列を使用しますtcp:port=5005,server=localhost

リモートデバッグの使用をスキップして、代わりにを使用できる場合があります{path to debugging tools}\windbg.exe %e。ただし、代わりにリモートを提案した理由はWerFault.exe、レジストリを読み取り、モニタープロセスを起動するものであると私が信じているため、セッション0でデバッガーが起動するためです。

セッション0をインタラクティブにしてウィンドウステーションに接続することはできますが、それがどのように行われたか思い出せません。また、開いていた既存のウィンドウのいずれかにアクセスする必要がある場合は、セッションを切り替える必要があるため、不便です。

于 2013-01-16T00:02:14.027 に答える
7

Tools->Debugging->General->Enable .Net Framework Debugging

+

Tools->IntelliTace-> IntelliTaceEbents And Call Information

+

Tools->IntelliTace-> Set StorIntelliTace Recordings in this directory

ディレクトリを選択します

INTO .netコードにステップインし、すべての関数呼び出しをトレースできるようにする必要があります。小さなサンプルプロジェクトで試してみましたが、うまくいきました

各デバッグセッションの後に、デバッグセッションの記録を作成することを想定しています。間違えなければCLRが死んでも設定ディレクトリ

これにより、CLRが崩壊する前に正確な呼び出しに到達できるようになります。

于 2013-01-09T16:20:40.190 に答える
3

一般的な例外ハンドラーを作成して、アプリを強制終了する未処理の例外があるかどうかを確認してください。

    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);
于 2013-01-09T15:37:22.070 に答える
3

私は通常、Valgrindとgdbのメモリ関連の問題を調査します。

Windowsで物事を実行する場合、ここで提案されているように、callgrindの非常に眠いなど、多くの優れた代替手段があります。Windows
の優れたValgrindの代替品はありますか?

.NETランタイムの内部エラーを本当にデバッグしたい場合は、クラスライブラリとVMのどちらにもソースがないという問題があります。

持っていないものをデバッグすることはできないので、(問題の.NET FrameworkライブラリをILSpyで逆コンパイルし、それらをプロジェクトに追加することは別として、まだvmをカバーしていません)使用することをお勧めしますモノランタイム。
そこには、クラスライブラリとVMの両方のソースがあります。
たぶんあなたのプログラムはmonoでうまく動作します、そして少なくともそれが1回限りの処理タスクである限り、あなたの問題は解決されるでしょう。

そうでない場合は、 GDBサポートhttp://www.mono-project.com/Debuggingを含むデバッグに関する広範なFAQがあります。

Miguelには、valgrindのサポートに関する次の投稿もあります:http:
//tirania.org/blog/archive/2007/Jun-29.html

それに加えて、Linuxで実行させる場合は、straceを使用して、syscallで何が起こっているかを確認することもできます。WinFormの広範な使用法やWinAPI呼び出しがない場合、.NETプログラムは通常Linuxで正常に動作します(ファイルシステムの大文字と小文字の区別に関する問題については、大文字と小文字を区別しないファイルシステムをループマウントするか、MONO_IOMAPを使用できます)。

あなたがWindows中心の人なら、この投稿 はWindowsが持っている最も近いものはWinDbgのLogger.exeであると言っていますが、ltrace情報はそれほど広範ではありません。

モノソースコードはここから入手できます:http:
//download.mono-project.com/sources/

あなたはおそらく最新のモノバージョンのソースに興味があります
http://download.mono-project.com/sources/mono/mono-3.0.3.tar.bz2

フレームワーク4.5が必要な場合は、mono 3が必要です。コンパイル済みのパッケージは、
https: //www.meebey.net/posts/mono_3.0_preview_debian_ubuntu_packages/にあります。

ソースコードを変更したい場合は、次のようにコンパイルします。http://ubuntuforums.org/showthread.php?t=
1591370

于 2013-02-13T21:51:30.170 に答える
1

キャッチできない.NET例外があります。チェックアウト: http: //msdn.microsoft.com/en-us/magazine/dd419661.aspx

于 2013-01-15T21:27:36.960 に答える