PHP 8.5: Поддержка трассировки стека для фатальных ошибок PHP

В PHP 8.5 появилась функция трассировки стека для фатальных ошибок, упрощающая процесс отладки приложений. Теперь разработчики могут видеть полный путь выполнения кода до момента возникновения критической ошибки, что существенно ускоряет поиск и устранение проблем. В статье рассматривается новая INI-директива `fatal_error_backtraces`, ограничения и взаимодействие с существующими инструментами обработки ошибок.

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

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

Однако в PHP всё ещё существуют определённые неисправимые ошибки, при возникновении которых просто выводится сообщение об ошибке и происходит немедленный выход из программы (после вызова функции завершения работы, если она задана с помощью register_shutdown_function и её можно вызвать на данном этапе).

ini_set('memory_limit', '2M');

function my_heavy_function(): void {
$str = str_repeat('A', 1024 * 1024 * 5);
}

my_heavy_function();

Вышеприведённый фрагмент PHP кода вызывает фатальную ошибку, поскольку в нём устанавливается значение memory_limit равным 2 МБ, а функция my_heavy_function() потребляет больше памяти, чем это ограничение.

До PHP 8.5, PHP завершается с таким сообщением:

Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 5242912 bytes) in ... on line ...

Хотя в сообщении об ошибке указаны имя файла и номер строки, в которой произошла ошибка, в нём отсутствует трассировка стека. Без трассировки стека сложно отследить стек вызывающих функций, приведших к этой строке в скрипте.

В PHP 8.5 добавлена новая возможность, благодаря которой сообщения о фатальных ошибках содержат полную трассировку стека:

Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 5242912 bytes) in /mnt/w/localhost/test/php85/error_handlers.php on line 6
Stack trace:
#0 file.php(...): str_repeat('A', 5242880)
#1 file.php(...): my_heavy_function()
#2 {main}

Новая INI-директива fatal_error_backtraces

Новая трассировка стека фатальных ошибок включена по умолчанию и может быть отключена с помощью новой INI-директивы fatal_error_backtraces.

Например, для отключения трассировки фатальных ошибок установите INI директиву, как показано ниже:

fatal_error_backtraces = Off

Совместимость с другими инструментами обработки ошибок

Новая возможность трассировки фатальных ошибок работает также с другими INI директивами.

Почему обратные трассировки включаются только для фатальных ошибок

Трассировки, включающие аргументы, приводят к увеличению счётчика ссылок для этих аргументов. В результате аргументы сохраняют активность вплоть до момента уничтожения трассировки.

Поскольку функция error_get_last возвращает трассировку последней возникшей ошибки, разработчики могут столкнуться с неожиданным поведением: объекты остаются активными дольше предполагаемого срока. Это продолжается либо до вызова функции error_clear_last, либо до возникновения новой ошибки.

Ограничение данной функциональности исключительно фатальными ошибками (E_FATAL_ERRORS) позволяет свести к минимуму указанный побочный эффект, ограничивая его лишь нестандартными ситуациями.

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

Кроме того, в современных PHP‑приложениях распространена практика преобразования предупреждений и уведомлений PHP в исключения посредством функции set_error_handler. В результате формируется обратная трассировка через объект Error.

Однако для фатальных ошибок (E_FATAL_ERRORS) создание трассировок невозможно — такие ошибки не поддаются обработке в коде приложения.

Влияние на обратную совместимость

Эта функция не вызывает никаких проблем с обратной совместимостью.

Установка INI директивы fatal_error_backtraces = Off отключает эту функциональную возможность. Однако обратите внимание, что отключение отображения ошибок с помощью директивы display_errors=Off является рекомендуемым способом защиты рабочих систем от утечки внутренней информации.

Комментарии


Дополнительные материалы

Предыдущая Статья

PHP 8.5: новая функция locale_is_right_to_left и Locale::isRightToLeft