2009-11-23 4 views
4

Я был удивлен, когда я просто попытался следующий PHP код:PHP не обрабатывает переполнение стека?

function foo() 
{ 
    foo(); 
} 
foo(); 

я ожидал, чтобы получить «500: Внутренняя ошибка сервера». Вместо этого соединение было немедленно закрыто (без байтов), а файлы журналов показывают, что apache segfaulted. WTF? Является ли это известной ошибкой в ​​PHP? Есть ли какие-то параметры конфигурации, которые мне не хватает? Потому что разбитый процесс для каждого случайного переполнения стека, ну ... довольно неприемлемый, я думаю.

+1

Вероятно компилятор видел, что ты там делал, и думал * о, мальчик, умное время ... оставьте меня в покое ... * –

+1

Без сомнения. Тем более, что PHP не имеет компилятора. : p –

+0

Я не думаю, что авария - это оптимизация. С другой стороны, как PHP должен обрабатывать что-то подобное более изящно? – innaM

ответ

5

PHP не способен справиться с этим, он просто перейдет в бесконечный цикл и произведет ошибку сегментации.

http://bugs.php.net/bug.php?id=49823

также

http://www.mail-archive.com/[email protected]/msg128905.html

+0

Sweet. Не могу дождаться до тех пор, пока не начнется обновление продукта до PHP 5.3. : P –

0

Я думаю, что это известная ошибка. См. Список Top 10 ways to crash PHP.

+1

Ссылка не работает. – MiffTheFox

+0

Интересная цитата из связанной статьи: «Во избежание использования рекурсивных функций они, как правило, плохая идея». – innaM

+0

Обновление страницы после загрузки заставит ее работать - странно ... – schnaader

1

Взятые из iBlog - Ilia Alshanetsky

переполнения стека. У PHP нет никакой внутренней защиты стека , выбрав , полагаясь на системный стек без защиты . Это означает, что если у вас есть рекурсивная функция или метод PHP в конечном итоге сбой.

function a() { a(); } a(); 

Есть 2 пути решения этой проблемы, 1 избегают использования рекурсивных функций они , как правило, плохая идея, так или иначе, и , если вы должны использовать их реализовать некоторые счетчик с помощью глобальной переменной, которая бы предотвратить функция из итерации себя более X количества времени для значений X от 500 до 1000. другого решения включает в себя использование расширения XDebug, что реализует защиту от стека переполнения путем определения предела того, насколько глубоко могут рекурсивные функции проходить через значение php.ini. Это лучшее решение в среде размещения, где у вас нет контроля над сценариями , которые запускаются на сервере.

+1

Хорошая информация о xdebug, но я бы оспаривал ваше утверждение о том, что рекурсивные функции - плохая идея. Да, они могут быть сложными в использовании, но в некоторых ситуациях (например, обход дерева) они являются наиболее эффективным способом. – dnagirl

+0

На самом деле его полностью взяли из другого места, и я подумал о комментировании плохих рекурсивных функций. Не поймите меня неправильно. Я знаю силу рекурсии, я просто не хотел изменять цитату. –

2

избежать, используя рекурсивные функции, которые они, как правило, плохая идея»0 riiight :))) они были изобретены, потому что его плохое ideea:)) ...

Я рекомендую настройки в HRD верхний предел на количество раз функция называется. НЕ использовать глобальные переменные (возможно, на самом деле нужно вызвать более рекурсивные функции, почему загрязняют глобал как это?). вы можете использовать дополнительные параметры для функции

function a($param1, $param2, $depth=100){ 
    $depth--; 
    if(!$depth==0) return error 
} 
+2

Это не главное. Конечно, я могу закодировать с помощью многих моих гарантий. Но ошибки неизбежны, и рано или поздно также будет StackOverflow. Скорее всего, рекурсия не будет называться, как одна функция, вызывающая другую, которая, в свою очередь, вызывает первую. Наличие незаметного segfault в этом случае вообще не помогает. –

+0

Верно, не знаете, что произойдет, если используется отладочная версия модуля php. По умолчанию любое приложение, которое переполняет, будет генерировать segfault и выйти ... потому что это segfault. Специальный (медленный) код отладки должен быть добавлен в файл для обработки переполнения стека, вероятно, поэтому интерпретатор php не справляется с этим. Вы также можете попробовать использовать xdebug и/или suhosin – Quamis