Переполнение стека при игре с методами Ruby singleton в IRB
Как субъект утверждает, я испытал переполнение стека при игре с синглетными методами в 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 singleton/class?
4 ответа:
Во-первых, существует некая вещь под названием
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
Надеюсь, это поможет.
Вы создали объект и определили метод
Вот почему вы должны избегать использования зависящих от системы ключевых слов при определении собственных методов, в вашем примере это может быть так:class
для этого объекта. И тогда в этом методе вы вызываете тот же самый методclass
- у вас есть бесконечная рекурсия.class << c def klass "my class is #{self.class}" end end
Стек возникает из модели памяти компьютеров.
Для каждой программы существует
heap
иstack
. Часть кучи сейчас не имеет значения.Когда программа вызывает функцию, происходит несколько вещей.
- текущая позиция программы помещается в стек
- переменные текущей области помещаются в стек
Когда вы оставляете функцию, эти действия реверсируются в обратном порядке, чтобы воспроизвести состояние программы перед вызовом функции.
Поэтому, когда ваша функция вызывает саму себя (что она и делает), она помещает строку "my class is" и текущую позицию программы в стек и запускает функцию снова, что делает то же самое.Это продолжается в течение многих итераций, пока вы не превысите объем стека, зарезервированного для вашей программы. (Это зависит от вашей операционной системы и, в конечном счете, от объема доступной оперативной памяти и всегда является конечным.) Это когда вы получаете это исключение. Система сообщает вам, что у нее закончилось пространство стека.
Обычно это происходит только с рекурсией, которая не имеет условия остановки.