Как восстановиться после фатальной ошибки «Разрешенный объем памяти исчерпан» - PullRequest
12 голосов
/ 23 февраля 2010

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

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

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

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

Спасибо

Ответы [ 7 ]

9 голосов
/ 23 февраля 2010

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

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

8 голосов
/ 21 февраля 2013
if((memory_get_usage() / 1024 /1024) < 70)

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

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

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

4 голосов
/ 23 февраля 2010

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

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

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

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

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

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

2 голосов
/ 22 апреля 2010

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

2 голосов
/ 23 февраля 2010

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

1 голос
/ 23 ноября 2011

Для меня это работало нормально:

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

Предполагается, что предел вашей памяти указан в формате 123M.

1 голос
/ 23 февраля 2010

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

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

...