【问题标题】:Preventing StackOverFlow in recursive functions在递归函数中防止 StackOverFlow
【发布时间】:2011-01-28 06:31:19
【问题描述】:

我在 BaseClass 中有一个递归函数,它的返回条件依赖于 protected virtual 函数。

子类可能会错误地覆盖此函数并导致StackOverFlow 异常。最糟糕的是有一些缓慢的网络调用,并且不会很快发生异常(很多资源浪费了很长时间)。

我正在寻找一种在早期阶段以某种方式在基类中检查StackOverFlow 的方法(可能使用Reflection 和当前的递归级别)。

有什么想法吗?

【问题讨论】:

  • ^投票给关于stackoverflow的话题。

标签: c# reflection stack-overflow


【解决方案1】:

您可以将一个简单的整数“深度”传递给递归函数,并在每次后续调用时递增它。如果它大于允许的最大深度,则立即抛出异常,而不是等到为时已晚并且可怕的StackOverflow 异常已经发生。

这样的安全机制(增量计数器,检查它是不是大到愚蠢)也可以在 while 循环中派上用场,其中一个小错误可能导致无限循环消耗大量 CPU。

在具有许多用户(例如网站)的大型系统中,有时最好采取诸如递归和 while 循环之类的预防措施,因为其后果可能远远超出一个网页或系统的一个用户。这不是漂亮的代码,纯粹主义者无疑会犹豫不决,但它是高效的,它是防御性的,而且是实用的。

【讨论】:

  • 不可能,Ian Mercer 在这里发帖?
  • bool RecursiveConditionMethod(ref int depthLevel) { depthLevel++; // if (depthLevel > MAX_DEPTH_LEVEL) break the loop 可以吗?
  • @Xaqron,我不会那样使用 ref int 。我会在方法调用自身时传递 depth+1 并首先检查方法内部的深度。例如,在树搜索中,您可能不想限制访问的节点总数,但您可能希望确保它不会卡在某个循环中,因为树是一棵合适的树。
【解决方案2】:

解决问题而不是创建解决方法。创建一个调用受保护虚函数的递归私有函数。

【讨论】:

  • 没办法。返回条件直到运行时才会显示给基类,这是由子类通过覆盖该方法提供的。
  • ?为什么你的基类应该依赖一个子类被覆盖的实现?
  • 子类是通过基类共享大量工作的插件。如果一个孩子需要深入它,它是允许的,但代码本身在基类中并在孩子之间共享。
【解决方案3】:

虽然您可能可以读取调用堆栈并对其进行分析,但我不会这样做。

  1. 它会减慢执行速度
  2. 这不是你的基类的责任
  3. 记录您的基类的行为

另一种方法是仅在调试模式下进行调用堆栈分析。下面是一段小代码,看看如何获​​取调用栈。

using System.Diagnostics;

[STAThread]
public static void Main()
{
  StackTrace stackTrace = new StackTrace();           // get call stack
  StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)

  // write call stack method names
  foreach (StackFrame stackFrame in stackFrames)
  {
    Console.WriteLine(stackFrame.GetMethod().Name);   // write method name
  }
}

From this site

【讨论】:

    猜你喜欢
    • 2018-07-25
    • 2017-09-21
    • 2021-03-30
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多