我在JIT/CLR中发现了一个错误 - 现在我该如何调试或重现它?

Blu*_*eft 24 .net c# debugging jit compiler-errors

我有一个计算成本高昂的多线程C#应用程序,在运行30-90分钟后似乎一直崩溃.它给出的错误是

运行时遇到了致命错误.错误的地址是0xec37ebae,在线程0xbcc上.错误代码是0xc0000005.此错误可能是CLR中的错误,也可能是用户代码的不安全或不可验证部分中的错误.此错误的常见来源包括COM-interop或PInvoke的用户编组错误,这可能会破坏堆栈.

(0xc0000005是访问冲突的错误代码)

我的应用程序不会调用任何本机代码,或使用任何不安全的块,甚至任何非CLS兼容的类型,如uint.实际上,调试器所说的导致崩溃的代码行是

overallLength += distanceTravelled;
Run Code Online (Sandbox Code Playgroud)

两个值都是类型的 double


考虑到这一切,我认为崩溃必定是由于编译器或CLR或JIT中的错误造成的.我想找出导致它的原因,或者至少写一个较小的复制品发送到微软,但我不知道从哪里开始.我从来没有必要查看CIL二进制文件,或编译的JIT输出,或本机堆栈跟踪(崩溃时没有托管堆栈跟踪),所以我不确定如何.我甚至无法弄清楚如何在崩溃时查看所有变量的状态(很遗憾,VS不会告诉我像在托管异常之后那样,并将它们输出到控制台/文件会减慢应用程序1000倍,这显然不是一个选项).

那么,我该如何调试呢?


[编辑]在VS 2010 SP1下编译,运行最新版本的.Net 4.0 Client Profile.显然它是".Net 4.0C/.Net 4.0E,.Net CLR 1.1.4322"

Jon*_*eet 22

我想找出导致它的原因,或者至少写一个较小的复制品发送到微软,但我不知道从哪里开始.

"较小的再现"在这里听起来确实是一个好主意......即使"较小"并不意味着"更快地再现".

在开始之前,尝试在另一台计算机上重现错误.如果你不能在另一台机器上重现它,那就建议做一整套不同的测试 - 硬件,安装等.

另外,请检查您是否有最新版本的所有内容.花这些时间来调试它(这很可能,我很害怕)然后最终得到"是的,我们知道这个 - 这是.NET 4中的一个错误,它已经在.NET 4.5中得到修复" 例如.如果你可以在各种框架版本上重现它,那就更好:)

接下来,删除程序中的所有内容:

  • 它有用户界面吗?如果可能,删除它.
  • 它使用数据库吗?看看你是否可以删除所有数据库访问:绝对是以后没有使用的任何输出,理想情况下也是输入.如果您可以在应用程序中硬编码输入,那将是理想的 - 但如果没有,文件比数据库访问更容易复制.
  • 它对数据敏感吗?同样,在不了解应用程序的情况下,很难知道这是否有用,但假设它正在处理大量数据,您是否可以使用二进制搜索来查找导致问题的相对少量的数据?
  • 必须是多线程的吗?如果你可以删除所有线程,显然可能需要更长的时间来重现问题 - 但是它仍然会发生吗?
  • 尝试删除一些业务逻辑:如果您的应用程序是适当的组件化,您可以通过首先创建存根实现,然后简单地删除调用来伪造整个重要组件.

所有这些都将逐渐减小应用程序的大小,直到它更易于管理.在每一步,您都需要再次运行应用程序,直到它崩溃或您确信它不会崩溃.如果您有很多可用的机器,那应该有帮助......

  • 只是一个更新:它出现[ponsfonze发现我的问题](http://stackoverflow.com/a/14001081/238419).当然,这是一个在.Net 4.5中修复的问题......我本应该听你的! (4认同)

小智 10

tl; dr 确保您正在编译.Net 4.5


这听起来像是在这里发现的同样错误.从MSDN页面:

当垃圾收集器释放并压缩内存时,可能会遇到此错误.启用"并发垃圾收集"并发生前景垃圾收集和后台垃圾收集的某种组合时,可能会发生此错误.发生这种情况时,您将反复看到相同的调用堆栈.在堆上,您将看到一个自由对象,在它结束之前,您将看到另一个自由对象破坏堆.

修复是编译到.Net 4.5.如果由于某种原因,你不能做到这一点,你也可以禁用并发垃圾回收通过禁用gcConcurrent该在app.config文件中:

<configuration>
   <runtime>
       <gcConcurrent enabled="false"/>
   </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)

或者只是编译到x86.


psu*_*lek 6

下载调试诊断工具v1.2

  1. 运行程序
  2. 添加规则"崩溃"
  3. 选择"特定流程"
  4. 如果您知道哪个例外它失败了,或者只是按原样保留此页面,则高级配置会在页面上设置您的例外
  5. 设置userdump位置

现在等待进程崩溃,DebugDiag创建日志文件.现在激活选项卡Advanced Analysis,在顶部列表中选择Crash/Hang Analyzers并在下面的列表中转储文件,然后点击Start Analysis.这将为您生成HTML报告.希望您在该报告中找到有用的信息.如果您有分析问题,请在某处上传html报告并将URL放在此处,以便我们可以专注于它.