C#无法捕获StackOverflowException或查看它发生的位置

我知道这很模糊,但这是我能收集到的。 我希望有人能够了解这可能会如何发生。

我有一个64位程序,我在Win 7 64bit机器上运行,内置在Visual Studio 2012中。

它使用位于另一个项目中的类(编译为dll)。 该类有一个错误的迭代器,可能导致堆栈溢出。 调用该buggy迭代器的操作是通过任务调用的。

所以在我的程序中,代码如下所示:

new Task(()=>{ try { DoWork(); //<-- buggy iterator is called inside } catch (Exception ex) { //Exception reported to user } }).Start(); 

代码每次都在相同的数据上执行,并且没有随机变量或guid生成,所以每次都应该产生相同的输出。

大多数情况下,它会在未知模块中发生StackOverflowException崩溃(尽管我知道它确实发生的地方)。 如果发生这种情况,我无法查看发生溢出的代码中的点,并且try-catch块什么都不做! 我无法继续执行该程序(如果我在没有调试的情况下运行它,它会显示“程序必须关闭以便在线检查解决方案”系统窗口)。

现在,它有时会捕获exception(显示导致exception的代码中的正确位置)。 这是随机的,但如果我更频繁地破坏任务(比如在工作期间随机插入断点),似乎会发生更多。

但是,我还是无法继续申请。 即使exception发生在一个try-catch块中,它应该捕获StackOverflowException(它应该捕获它,因为StackOverflowException包含在Exception中 – C#不会让你捕获它们并明确告诉你SOE已经包含在E中)。

我尝试制作一个小程序,在try-catch块内部故意堆栈溢出,它还显示“程序必须关闭,让在线检查解决方案”系统窗口,而不是正确处理。 这是代码:

  private bool Overflow() { return Overflow(); } private void button1_Click(object sender, EventArgs e) { try { Overflow();} catch (StackOverflowException ex) { } } 

因此,我有几个问题:

问题1:

是否有可能捕获StackOverflowExceptions? 我该怎么做?

问题2:

当你的dll(同一解决方案中的其他项目)内发生堆栈溢出时,什么可以使VS 2012调试器认为它是“未知模块”?

问题3:

为什么要与部落乐器进行一些奇妙的魔术舞蹈,这样可以减少这种情况? (我的意思是随机打破正在进行的程序)

总的来说,发生了什么?

提前致谢

您不能捕获真正的堆栈溢出exception,这就是为什么它不起作用。

另见本讨论。

我不能回答你的第二个问题,除了说“程序真的搞砸了”。

对于你的第三个问题:因为它在一个单独的线程中运行,它运行的代码量将根据你打破程序的时间而有所不同。 我认为你能够解决这个问题的唯一方法是通过一些繁琐的逐行调试,或者许多Debug.WriteLine()。

1)从.NET Framework 2.0版开始,try-catch块无法捕获StackOverflowException对象,默认情况下会终止相应的进程。 因此,建议用户编写代码以检测并防止堆栈溢出。 例如,如果您的应用程序依赖于递归,请使用计数器或状态条件来终止递归循环。 请注意,承载公共语言运行库(CLR)的应用程序可以指定CLR卸载发生堆栈溢出exception的应用程序域,并让相应的进程继续。 有关更多信息,请参阅ICLRPolicyManager接口和主机概述。 ( http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx