PHP, достигший предела памяти, вызывает перезапуск функции - PullRequest
1 голос
/ 22 апреля 2009

Итак, у меня очень странная проблема.

Во-первых, я использую PHP 5.2.6 (как часть MAMP, хотя это также происходит на сервере LAMP под управлением 5.2.6), пишу веб-сайт с использованием Zend Framework 1.7.2.

Во-вторых, программное обеспечение, которое я пишу, выполняет довольно сложный статистический расчет, который требует много памяти. Обычно он работает нормально с ограничением памяти в 128 МБ.

Итак, вот самое интересное.

У меня есть класс, который отвечает исключительно за получение необходимых данных, выполнение необходимых вычислений и возврат значений. После того, как он запустился, я отключил его, так как PHP, кажется, думает, что он все еще находится в области видимости и удерживает память для него, несмотря на завершение функции, в которой он вызывается (это вызывало проблемы, когда второй прогон вычисления был удар по пределу памяти и скрипт умер). После того, как этот расчет выполняется один раз внутри этой функции, он снова запускается в другой функции для выполнения другого вычисления (это происходит во время того же самого выполнения). Вот где все становится странным.

Если я выполню это второе вычисление, вызывающая функция снова запустится, несмотря на то, что в коде, выполняющем это вычисление, нет абсолютно никаких вызовов этой функции. Также в PHP не появляются ошибки или предупреждения.

Однако, если я увеличу предел памяти (скажем, до 1024 МБ), этого не произойдет. Общая вызывающая функция запускается один раз и продолжает свой веселый путь.

Итак, позвольте мне нарисовать карту ниже.

function A{
   calls function B
   calls function D
}

function B{
   calls calculation function C
}

function D{
   calls calculation function C
}

с 128 МБ памяти, путь функций следующий (внутри и обратно к вызывающей стороне): A-> B-> C-> B-> A-> D-> C-> D-> затем он запускает A от начала функции, по какой-то причине, до конца (есть условный случай, который становится истинным во время этого пути выполнения, поэтому путь не повторяется)

с 1 ГБ памяти, путь функций следующий: A-> B-> C-> B-> A-> D-> C-> D-> конец A, что и должно быть.

Если я уберу второе вычисление из функции D, оно сработает. Если у меня до предела памяти, это работает.

Вопрос: нашел ли я ошибку в управлении памятью PHP? Или, может быть, в Zend Framework? Снова; Увеличивая лимит памяти на скрипт в php.ini, я не вижу этой проблемы. Или удалите второй экземпляр этого вычисления, который использует много памяти.

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

Ответы [ 2 ]

1 голос
/ 22 апреля 2009

Проверено ли выполнение программы с помощью debug_backtrace () ? Я думаю, что более вероятно, что ваш PHP-код является причиной этого, чем Zend Engine. Я бы порекомендовал помещать дамп трассировки в файл в начале каждой функции и сначала анализировать:

function myFunction() {
    file_put_contents(print_r(debug_backtrace(), true) . "\n--\n", 'trace.txt');
    //...
0 голосов
/ 22 апреля 2009

Во-первых, включите все сообщения об ошибках , включая E_STRICT.

Я подозреваю, что из-за нехватки памяти путь выполнения вы не ожидали, и, возможно, дополнительные сообщения об ошибках прольют больше света.

...