Уровень стека Ruby слишком глубокое исключение НЕ из рекурсивного бесконечного цикла
РЕДАКТИРОВАТЬ: (решено) на самом деле это, вероятно, было поднято из-за бесконечного цикла
Я кодировал и после добавления метода я получил это:
user_name@the_computer:/media/ECC3-C3B0/Prog/mts/src/mts$ rake test --trace
** Invoke test (first_time)
** Execute test
/home/user_name/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36: stack level too deep (SystemStackError)
rake aborted!
Command failed with status (1): [/home/user_name/.rvm/rubies/ruby-1.9.3-p19...]
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils.rb:53:in `block in create_shell_runner'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils.rb:45:in `call'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils.rb:45:in `sh'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils_ext.rb:39:in `sh'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils.rb:82:in `ruby'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils_ext.rb:39:in `ruby'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/testtask.rb:99:in `block (2 levels) in define'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/file_utils_ext.rb:60:in `verbose'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/testtask.rb:98:in `block in define'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `call'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `block in execute'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `each'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `execute'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:158:in `block in invoke_with_call_chain'
/home/user_name/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/task.rb:144:in `invoke'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:116:in `invoke_task'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block (2 levels) in top_level'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `each'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block in top_level'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:88:in `top_level'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:66:in `block in run'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/lib/rake/application.rb:63:in `run'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/gems/rake-0.9.2.2/bin/rake:33:in `<top (required)>'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/bin/rake:19:in `load'
/home/user_name/.rvm/gems/ruby-1.9.3-p194@global/bin/rake:19:in `<main>'
/home/user_name/.rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:in `eval'
/home/user_name/.rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => test
Я почти уверен, что здесь нет бесконечного рекурсивного цикла.
Код на данный момент как-то разложен, но я также получил ошибку при запуске файла ruby напрямую.
Спасибо за любую помощь о том, как (получить некоторую информацию, выполнить некоторые тесты для), чтобы исправить проблему, если это возможно, без необходимости переписывать все это...
Среда:
- ruby 1.9.3p194 / rails 3.2.8, устанавливается через rvm
- программа на данном этапе использует только функции рельсов строк
- ОС: linux kubuntu i386
- память 4GO
- 'ulimit -s': 8192 (размер стека в КБ)
Что я безуспешно пытался:
- удалил кусок кода, где изначально возникла исключительная ситуация, но она все же была поднята чуть позже во время выполнения
- установить размер стека с помощью командной строки 'ulimit -s 20000', 'ulimit -s unlimited'. Та же ошибка, видимо, в том же месте (что заставляет меня думать, что размер стека фактически не изменился)
- понижен до ruby1.9.2 / rails3.1.3, получил то же сообщение
- та же ошибка под виндой
Контекст приложения:
Я пишу приложение, в котором интенсивно используются рубиновые миксины.
Кроме того, я создал группу классов, которые генерируют миксины (модули методов экземпляра / класса, которые будут включены другими классами).
Таким образом, в итоге я получаю довольно много сгенерированных именованных модулей с некоторым собственным сгенерированным кодом и классы со многими предками.
Но это должно в конечном итоге избавить меня от некоторой боли в виде $, когда я пишу программу, которая находится на вершине этой библиотеки (в любом случае, это план).
Ресурсы, которые я использовал:
- Как увеличить размер стека для приложения ruby. Получение рекурсивного приложения: уровень стека слишком глубокий (SystemStackError)
- http://dalibornasevic.com/posts/5-ruby-stack-level-too-deep-systemstackerror
РЕДАКТИРОВАТЬ: До тех пор, пока некоторый код не доступен для показа / тестирования, давайте абстрагируем мой вопрос до этого: Есть ли другие случаи, которые поднимают уровень стека слишком глубокое исключение, кроме классического сценария выполнения программы дерево слишком слишком глубоко (скрещивание пальцев это понятно и что-то значит...)?
1 ответ
Существуют ли другие случаи, которые поднимают уровень стека на слишком глубокое исключение, кроме классического сценария "дерево выполнения программы слишком глубокое"?
Да. Поскольку стек измеряется не глубиной, а байтами, все, что хранится в стеке, заполнит его быстрее:
def recurse(depth=0)
recurse depth+1
rescue SystemStackError
depth
end
=> nil
recurse
=> 8717
def recurse(depth=0)
a,b,c = 1,2,3
recurse depth+1
rescue SystemStackError
depth
end
=> nil
recurse
=> 7264
def recurse(depth=0)
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z = *(0..25)
recurse depth+1
rescue SystemStackError
depth
end
=> nil
recurse
=> 3187
В этом примере функция только с одной переменной может выполнить несколько тысяч вызовов до сбоя, а добавление еще трех переменных делает очень мало; но добавление еще 26 переменных увеличивает размер стека до точки, где доступно только около 3000 уровней.
Это, конечно, будет зависеть от реализации ruby и системы, на которой он работает. Но я верю, что это всегда будет соблюдаться как общее правило.
Тем не менее, я все еще думаю, что рекурсия, вероятно, является вашей проблемой, поскольку число переменных, необходимых для того, чтобы это происходило при малых длинах цепочки вызовов, огромно.