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

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

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

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

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

спасибо

7 ответов


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

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


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

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

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

многие могут спорить; о, Эй, ваше программное обеспечение не оптимизировано. Да. Вероятно, вы правы; но со сложными наборами данных вы можете сжать только столько производительности прежде чем вам нужно бросить больше памяти на него; и выслеживание ошибок памяти в потоке 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() называется.

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

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


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


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


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

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

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


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

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