Как восстановить из фатальной ошибки "Допустимый размер памяти"

Знаете ли вы какое-либо решение для восстановления после фатальной ошибки PHP: "Разрешенный размер памяти... исчерпан"

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

Проблема в том, что, когда памяти больше нет, она не может зарегистрировать ошибку (я вхожу в Firebug через FirePHP с Zend Framework).

Итак, что я имею в виду под термином "как его восстановить", как выполнить основной журнал ошибок, и пусть Zend Framework отправляет заголовки, чтобы ошибка регистрировалась (в Firebug в моем случае) как любая другая ошибка?

Спасибо

Ответ 1

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

Существует еще один тип ошибок - "уловимая фатальная ошибка", которая, как следует из названия, может быть обнаружена в try/catch, но, к сожалению, распределение размера памяти не является одним из них.

Ответ 2

if((memory_get_usage() / 1024 /1024) < 70)

Я просто разделил memory_get_usage на квадрат 1024, чтобы сравнить его с "нормальным" мегабайтным значением "70".

Я столкнулся с проблемами памяти с php внутри цикла for и написал этот простой оператор if, чтобы предотвратить script от установки фатальной ошибки. Кроме того, сервер, на котором я работал, не позволял мне изменять пределы памяти (это часто бывает в некоторых облачных предложениях, таких как openhift или крупные веб-хосты, такие как dreamhost.) Я действительно не заметил серьезных ухудшений производительности ( в php 5.3, который может обрабатывать такие функции несколько иначе, чем php 4.x или 5.x... во всяком случае, последствия производительности script, дающие фатальную ошибку, перевешивают любые накладные расходы, вызванные вызовом функции. также предотвращает отрыв от script от всех доступных плунжеров.

Многие могут спорить; о, ваше программное обеспечение не оптимизировано. Да. Возможно Вы правы; но со сложными наборами данных вы можете только выжать так много производительности, прежде чем вам нужно будет залить больше памяти; и поиск ошибок памяти в потоке ajax может быть очень расстраивающим; особенно если вы не знаете, где находятся ваши файлы журналов.

Ответ 3

Обычный способ настройки обработки ошибок - через

set_error_handler - Устанавливает пользовательскую функцию обработчика ошибок

Документы для этой функции (основное внимание):

Следующие типы ошибок не могут обрабатываться с помощью определенной пользователем функции: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING и большая часть E_STRICT, поднятых в файле, где вызывается set_error_handler().

Итак, он не будет работать регулярно, но вы можете попробовать

Как и в случае с PHP7, ошибки и исключения являются Throwables, поэтому вы можете попробовать/поймать их:

Ответ 4

Ошибки PHP отправляются по умолчанию в ваш журнал ошибок apache /path/to/apache/logs/error.log, и вы можете видеть его там.

Ответ 5

Получил идею непроверенного трюка, и я был бы рад узнать, помогло ли это. Выделите некоторую глобальную переменную, когда вы сначала зарегистрируете функцию выключения и отпустите ее, когда сначала выполняется код функции выключения. Тогда у вас может быть достаточно памяти для создания объекта Exception. Сообщите мне, если это сработало и, пожалуйста, опубликуйте здесь код.

Ответ 6

Я могу подумать, что вы, когда выполняете интенсивную операцию с памятью, вручную запрашиваете memory_get_usage() на регулярной основе (например, каждую итерацию цикла) и выгружаете свои заголовки/ошибки, когда они перехватывают некоторые отказоустойчивые значения который ниже предела script. Это значительно снизит ваш script, но по крайней мере вы получите что-то обратно.

Или, возможно, вы не сможете этого сделать, запустите интенсивную память, как основанную на CLI script, вызванную из вашего веб-материала с помощью exec. Часть CLI может упасть, но веб-часть сможет сообщить об этом.

Ответ 7

Это работало отлично для меня:

try {
    ini_set('memory_limit', (ini_get('memory_limit')+1).'M');
} catch(Exception $e) {}

Это предполагает, что ваш предел памяти находится в формате 123M.