【问题标题】:Why does setting a static method result in a stack overflow?为什么设置静态方法会导致堆栈溢出?
【发布时间】:2009-03-17 22:07:03
【问题描述】:

如果我在 C# 中使用 set 访问器更改静态类成员,为什么会出现堆栈溢出错误?

我并不认为这是一个错误,我只是想知道机器内部到底发生了什么。

【问题讨论】:

  • 你能举个例子吗?
  • 您遇到了 StackOverflowException,并立即访问了 StackOverflow.com。现在,这是您无法支付的娱乐。
  • 我想知道有多少人访问 www.argumentexception.com 却对找不到帮助感到失望。
  • 考虑注册 www.nullpointerexception.com

标签: c# .net static


【解决方案1】:

你不应该;我希望你有类似的东西:

private static int foo;
public static int Foo {
    get {return foo;}
    set {Foo = value;} // spot the typo!!! (should be foo)
}

基本上,set 是:

static void set_Foo(int value) {
    set_Foo(value);
}

所以这是递归的,最终会耗尽堆栈(假设没有优化等)。

没有代码示例就无法诊断更多。

【讨论】:

  • 可能是static被设置为一个事件处理函数的结果,而事件处理函数是通过设置属性来设置的(还有比较复杂的例子)真的需要看代码或者调用栈来确定问题
  • @Rowland - 也许吧,但静态事件通常是个坏主意,因为如果您忘记取消订阅,您的对象将无法被收集。永远。
  • 如果您覆盖继承的属性并忘记“基础”,则可能会在同一主题上发生变化。设置时的前缀。
  • 嘿,你知道如果 c# 有尾调用优化,那么这甚至不会导致堆栈溢出。请注意,这将是一个无限循环,因此可能不会有很大的改进
  • @1800 - 实际上,JIT 确实 有尾调用递归。它在 x86 和 x64 之间的实现方式不同,我希望 4.x/5.x 会有改进——但它就在那里。只是用的不多。
【解决方案2】:

我猜你正在做这样的事情:

public class MyClass
{
    public int TheInt
    {
    get
    {
        return TheInt;
    }
    set
    {
        TheInt = value; // assignment = recursion!
    }
}

问题是,在 TheInt 的 set 函数中,您为 TheInt 分配了一个值,这将导致对 set 函数的嵌套调用。你得到递归,然后堆栈溢出。

【讨论】:

    【解决方案3】:

    在调试器中查看您的调用堆栈(当抛出异常时您确实会停止,对吗?)这应该可以让您清楚地了解正在发生的事情。

    【讨论】:

      【解决方案4】:

      我想我看到了对这个问题的不同解释。问题不是为什么会发生溢出,而是为什么访问器会导致溢出。在这种情况下,访问器和其他任何函数一样都是函数调用,因此它确实会占用堆栈空间。

      如果您使用没有访问器的公共成员,MyClass.myint 不会成为函数调用,也不会溢出堆栈。

      【讨论】:

        【解决方案5】:

        您想知道内部发生了什么导致堆栈溢出?

        您的方法调用另一个导致无限递归的方法:A 调用 A,堆栈溢出。 A 调用 B,然后 B 调用 A,堆栈溢出。以此类推。

        正如 Marc Gravell 所建议的,您的属性实现中可能存在错误。

        【讨论】:

          猜你喜欢
          • 2014-12-20
          • 2018-07-01
          • 2010-09-11
          • 1970-01-01
          • 2011-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多