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

StackOverflow https://stackoverflow.com/questions/2318858

  •  22-09-2019
  •  | 
  •  

Вопрос

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

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

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

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

Спасибо

Это было полезно?

Решение

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

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

Другие советы

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

Обычный способ настройки обработки ошибок заключается в

set_error_handler — Устанавливает определяемую пользователем функцию обработчика ошибок.

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

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

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

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

Ошибки 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 может выйти из строя, но веб-часть сможет сообщить об этом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top