2011-01-19 37 views
20

场景:如何调试.NET中stackoverflowexception

我刚刚一直在滚动实施了一堆代码,但是当我执行它,我得到抛出StackOverflowException? StackOverflowException没有堆栈跟踪,所以我卡住了。我知道为什么会发生堆栈溢出,但为了解决这个问题,我需要知道它的根源在哪里。

所有我得到的是:类型System.StackOverflowException“未处理的异常发生在标签 - 您 - it.dll

选项:

  1. 扫描通过所有的改变并试图指出问题。 (可能很慢)
  2. 使用调试器并逐步通过,直到找到问题。 (可能优于1.)
  3. 使用配置文件并查找最常用的方法。

PS:

这是一个假设情况(尽管不太常见),因此没有代码是可用的。

+0

打印堆栈跟踪?当VS遇到一个stackoverflow异常时,VS往往会窒息。 – leppie 2011-01-19 11:32:11

+0

导致这个问题的代码被公开在链接问题http://stackoverflow.com/questions/39004357/how-to-fix-stackoverflowexception-in-net – Andrus 2016-08-18 07:53:19

回答

12

这几乎总是归因于递归。无论是调用自身的方法还是调用方法的方法,都会调用它,等等。

为了找到它:

  • 修订:我不知道,但显然你不能得到一个StackOverflowException(我猜的东西做不能够赶上一个堆栈跟踪,或者)。但有办法获得转储as mentioned here
  • ReSharper将显示调用自身的方法(它在递归调用的边栏中放置一个绿色圆圈),尽管在涉及两个或多个方法时它不会捕获递归。
  • 使用像ANTS Profiler这样的工具来查看哪些方法被调用次数最多。
  • 留意那些可能调用代码的事件,这意味着同一个事件再次触发,导致循环。

有时候,你会得到错别字这个样子,太:

private string name; 

public string Name 
{ 
    get { return Name; } // Ooops! This is recursive, all because of a typo... 
} 

这是一个原因,为什么我个人现在更喜欢使用自动属性。

-1

找到调用自己的方法(或一个方法调用另一个,反之亦然)并检查它们。递归通常是您发现SO异常时的主要嫌疑人。

+1

我知道他们为什么会发生。麻烦是跟踪他们。你只是说明选项1. – Christo 2011-01-19 11:09:45

1

在作为失败操作的“入口点”的方法中,放置一个断点。遍历代码并观察一遍一遍又一遍地以相同模式发生的相同方法调用序列的发生,以便调用堆栈变得越来越深。

只要您注意到,在当前位置放置一个断点,无论它在哪里。继续执行(Visual Studio中的F5) - 如果你在正确的轨道上,那么调试器将在相同的位置很快停止,并且调用堆栈将更深。

现在,您可以检查一个“实时”堆栈框架,以便弄清楚如何确保这种递归将正确终止。

+0

和Borja的建议一样。 – Christo 2011-01-19 11:38:35

+0

其他的解决方法(由'最旧'排序) – 2011-01-19 12:24:41

+0

;-) Jip,猜猜我的排序是错误的。我最初也投了你的票,以防万一我订购错了。 – Christo 2011-01-20 06:15:50

5

您可以在调试模式下执行程序并暂停它。在当前的调用堆栈中,您可以看到有多个方法或一组方法出现,这是有问题的方法。在这个方法上划一个断点,看看它自己始终在调用什么。

5

转到调试,异常并在'公共语言运行时例外'中检查抛出的复选框。现在当你引发stackoverflow异常时,调试器将停止(最终)并向你显示调用栈。

0

如果您有代码并且能够从Visual Studio运行程序,它应该在遇到System.StackOverflowException时在调试器中断开(如果启用了首次机会异常)。从那里你可以检查调用堆栈并查看哪些调用正在堆栈。 enter image description here

我确认这适用于Visual Studio 2010和Visual C#2010 Express。

0

个人而言,我喜欢尽可能将其缩小到某个代码段。例如,我只有一个。奇怪的是,它只发生在我无法直接调试的机器上。

我有两个线程并行运行,所以我停止了一个运行(或者你可以不并行)。

然后,我通过我的函数去,并加入像打印出来的功能,如: 正如函数开始:

Console.WriteLine("<Enter method: {0}", DebuggingHelper.GetCurrentMethod()); 

就在函数返回:

Console.WriteLine(">Exit method: {0}", DebuggingHelper.GetCurrentMethod()); 

凡GetCurrentMethod被定义为:

[MethodImpl(MethodImplOptions.NoInlining)] 
public static string GetCurrentMethod() 
{ 
    StackTrace st = new StackTrace(); 
    StackFrame sf = st.GetFrame(1); 
    return sf.GetMethod().Name; 
} 

然后我运行它,也许我不添加到所有功能,但足以缩小它发生的代码的位置。然后在该部分中添加更多内容。

您还可以在通过某些方法运行时添加检查点。

然后再次运行它,你会发现这些语句之间会发生StackOverFlow异常。继续缩小直到找到它。

很简单,快速找到这种情况。