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

Вы знаете какое-либо решение для восстановления после фатальной ошибки PHP: « Разрешенный размер памяти … исчерпан »

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

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

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

благодаря

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

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

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

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

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

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

Регулярный способ настройки обработки ошибок

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

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

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

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

  • подход, приведенный в комментариях руководства PHP, с использованием выходной буферизации или
  • подход с использованием функции register_shutdown_function

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

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

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

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

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

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

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

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