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

时间:2013-04-09 08:35:34

标签: c# visual-studio visual-studio-2012 stack-overflow

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

我有一个64位程序,我在Win 7 64位机器上运行,内置于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块什么都不做!我无法继续执行程序(如果我在没有调试的情况下运行它,它会显示“必须关闭程序才能检查解决方案在线”系统窗口)。

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

但是,我还是无法继续申请。尽管异常发生在一个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:

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

总的来说,发生了什么?

提前致谢

2 个答案:

答案 0 :(得分:1)

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

另见this讨论。

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

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

答案 1 :(得分:0)

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