Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在.NET运行时调试内部错误?_C#_.net - Fatal编程技术网

C# 如何在.NET运行时调试内部错误?

C# 如何在.NET运行时调试内部错误?,c#,.net,C#,.net,我试图调试一些处理大文件的工作。代码本身可以工作,但是.NET运行时本身报告了零星的错误。对于上下文,这里的处理是一个1.5GB文件(只加载到内存一次)在循环中被处理和释放,故意试图重现这个不可预测的错误 我的测试片段基本上是: try { byte[] data =File.ReadAllBytes(path); for(int i = 0 ; i < 500 ; i++) { ProcessTheData(data); // deserializ

我试图调试一些处理大文件的工作。代码本身可以工作,但是.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
}
试试看{
byte[]data=File.ReadAllBytes(路径);
对于(int i=0;i<500;i++)
{
ProcessTheData(数据);//反序列化和验证
//强制收集,以保持整洁
Collect(GC.MaxGeneration,GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
}
}捕获(例外情况除外){
控制台写入线(例如消息);
//更多日志记录;StackTrace、递归InnerException等
}
(加入了一些时间和其他东西)

循环将在不确定的迭代次数下正常运行完全成功-没有任何问题;然后,该过程将突然终止。未命中异常处理程序。该测试确实涉及大量内存使用,但在每次迭代过程中,它都非常有效(没有明显的内存泄漏,我有足够的空间,在最差的点上有14GB未使用的主内存)。该进程是64位的

windows错误日志包含3个新条目,这些条目(通过退出代码80131506)表明执行引擎错误-一个令人讨厌的小家伙。表示GC错误,带有“修复”以禁用并发GC;但是,此“修复”并不能阻止该问题

澄清:此低级错误不会影响
CurrentDomain.UnhandledException
事件

澄清:
GC.Collect
仅用于监控锯齿状内存,检查内存泄漏并保持可预测性;删除它并不会使问题消失:它只会使它在迭代之间保留更多内存,并使dmp文件更大;p

通过添加更多控制台跟踪,我观察到它在以下每种情况下都会出现故障:

  • 反序列化期间(大量分配等)
  • 在GC期间(在GC“方法”和GC“完成”之间,使用GC通知API)
  • 在验证期间(仅对部分数据进行
    foreach
    )-奇怪的是在验证期间GC“完成”之后
所以有很多不同的场景


我可以获得崩溃转储(dmp)文件;我如何进一步调查这一点,以了解系统在如此惊人地失败时正在做什么?

尝试编写一个通用异常处理程序,看看是否有未处理的异常导致应用程序死亡

    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);

工具->调试->常规->启用.Net Framework调试

+

Tools->IntelliTace->IntelliTaceEbents和呼叫信息

+

Tools->IntelliTace->在此目录中设置StorIntelliTace录制

然后选择一个目录

应该允许您进入.net代码并跟踪每个函数调用。 我在一个小样本项目上试用了它,效果很好

在每个调试会话之后,它将创建调试会话的记录。它是set目录 即使CLR死了如果我没弄错的话


这应该允许您在CLR崩溃之前访问extact调用。

存在无法捕获的.NET异常。签出:

如果您有内存转储,我建议使用WinDbg查看它们,假设您还没有这样做

正在尝试运行注释
!EEStack
(混合本机和托管堆栈跟踪),并查看堆栈跟踪中是否有任何可能跳出的内容。在我的测试程序中,我发现有一次我的堆栈跟踪发生了FEEE(我故意破坏堆):

0:000> !伊斯塔克 --------------------------------------------- 线程0 当前帧:ntdll!NtWaitForSingleObject+0xa 子SP RetAddr调用者,被调用者 00000089879bd3d0 000007fc586610ea内核库!WaitForSingleObjectEx+0x92,正在调用ntdll!NtWaitForSingleObject 000000 89879BD400 00000 7FC5869811C内核库!RaiseException+0x68,调用ntdll!RtlRaiseException [...] 00000089879bec80 000007fc49109cf6 clr!WKS::gc_heap::gc1+0x96,正在调用clr!WKS::gc_堆::标记_阶段 00000089879BECD000007FC49109C21 clr!WKS::gc\U堆::垃圾收集+0x222,调用clr!WKS::gc_堆::gc1 00000089879BED1000007FC491092F1 clr!WKS::GCHeap::RestartEE+0xa2,调用clr!线程::恢复运行时 00000089879bed60 000007fc4910998d clr!WKS::GCHeap::GarbageCollectGeneration+0xdd,调用clr!WKS::gc_堆::垃圾_收集 00000089879BEDB000007FC4910DF9C clr!WKS::GCHeap::Alloc+0x31b,正在调用clr!WKS::GCHeap::垃圾收集生成 00000089879BEE0000007FC48FF82E1 clr!JIT_NewArr1+0x481 由于这可能与垃圾收集器的堆损坏有关,因此我将尝试
!验证堆
命令。至少您可以确保堆是完整的(您的问题在别处),或者发现您的问题实际上可能是GC或某些P/Invoke例程破坏了它

如果您发现堆已损坏,我可能会尝试发现堆中有多少已损坏,您可以通过
执行此操作!HeapStat
。不过,这可能只是显示整个堆在某一点上已损坏

很难通过WinDbg推荐任何其他方法来分析这一点,因为我对您的代码正在做什么或它是如何构造的没有真正的线索

我想如果您发现这是堆的一个问题,因此意味着这可能是GC的怪异之处,那么我将研究Windows的事件内跟踪


如果您得到的小转储没有剪切它,并且您使用的是Windows 7/2008R2或更高版本,那么如果您没有获得,则可以在进程终止时使用全局标志(gflags.exe)附加调试器,而不会出现异常 0:000> !EEStack --------------------------------------------- Thread 0 Current frame: ntdll!NtWaitForSingleObject+0xa Child-SP RetAddr Caller, Callee 00000089879bd3d0 000007fc586610ea KERNELBASE!WaitForSingleObjectEx+0x92, calling ntdll!NtWaitForSingleObject 00000089879bd400 000007fc5869811c KERNELBASE!RaiseException+0x68, calling ntdll!RtlRaiseException [...] 00000089879bec80 000007fc49109cf6 clr!WKS::gc_heap::gc1+0x96, calling clr!WKS::gc_heap::mark_phase 00000089879becd0 000007fc49109c21 clr!WKS::gc_heap::garbage_collect+0x222, calling clr!WKS::gc_heap::gc1 00000089879bed10 000007fc491092f1 clr!WKS::GCHeap::RestartEE+0xa2, calling clr!Thread::ResumeRuntime 00000089879bed60 000007fc4910998d clr!WKS::GCHeap::GarbageCollectGeneration+0xdd, calling clr!WKS::gc_heap::garbage_collect 00000089879bedb0 000007fc4910df9c clr!WKS::GCHeap::Alloc+0x31b, calling clr!WKS::GCHeap::GarbageCollectGeneration 00000089879bee00 000007fc48ff82e1 clr!JIT_NewArr1+0x481