2

正如主题所述,在 IRB 中使用单例方法时,我遇到了堆栈溢出。以下是我尝试过的代码:

c= C.new
class << c
  def class
    "my class is #{self.class}."
  end
end

当我打电话c.class时,我得到了一个:

SystemStackError: stack level too deep
Maybe IRB bug!

我找到了有关如何调整堆栈大小的参考,但首先不了解堆栈大小。

问题: 为什么我在 IRB 中收到该错误?另外,我怎样才能继续试验 Ruby 单例/类方法?

4

4 回答 4

3

首先,有一些东西叫做recursion函数可以调用自己的地方。这是您在代码中无意中所做的。

第二件事,堆栈是维护函数调用跟踪的东西。这样当达到递归结束或堆栈级别深度时,它可以正确地恢复程序。

它是这样的:假设你有函数 A 和函数 B。

function A {
  /* some code */
  B()
  /* some more code */
}

function B {
  return / * something * /
}

您的机器基本上停止执行 A,将 A 中变量的状态保存到堆栈中,调用并执行 B。当最终 B 退出时,它从堆栈中弹出并继续执行 A。

在该特定示例中,因为您希望定义自己的class方法。下面的代码应该做:

def class
  "my class is #{super}"
end

希望这可以帮助。

于 2013-02-09T14:21:35.470 回答
1

您已经class为该对象创建了对象并定义了方法。然后在这个方法中你调用相同的方法class——你有无限递归。

这就是为什么在定义自己的方法时应避免使用依赖于系统的关键字的原因,在您的示例中可能是这样的:

class << c
  def klass
    "my class is #{self.class}"
  end
end
于 2013-02-09T14:09:50.160 回答
1

堆栈源自计算机的内存模型。

对于每个程序,都有heapstack。堆部分现在并不重要。

当一个程序调用一个函数时,会发生几件事。

  • 程序的当前位置放在栈上
  • 当前作用域的变量放在栈上

当您离开一个函数时,这些操作会以相反的顺序反转,以便在调用函数之前复制程序的状态。

因此,当您的函数调用自身(它确实如此)时,它将字符串“my class is”和当前程序位置放在堆栈上并再次启动该函数,这也是如此。

这会持续多次迭代,直到超过为程序保留的 auf 堆栈数量。(这取决于您的操作系统,最后取决于可用的 ram 数量,并且始终是有限的。)这就是您遇到此异常的时候。系统通知您,堆栈空间不足。

这通常只发生在没有停止条件的递归中。

于 2013-02-09T14:17:19.430 回答
0

除了解释堆栈如何工作的所有不错的答案之外,

class是 Ruby 中的保留关键字。该方法Object#class是一个独特的例外。你无法真正重新定义它。

于 2013-02-09T15:20:51.790 回答