在PHP中安全地捕获“允许的内存大小已耗尽”错误

我有一个网关脚本,返回到客户端的JSON。 在脚本中,我使用set_error_handler来捕获错误,并仍然有一个格式化的返回。

它受到“允许的内存大小耗尽”的错误,但不是像ini_set('memory_limit','19T')那样增加内存限制,我只是想返回用户应该尝试其他的东西,因为它过去很多记忆。

有没有什么好方法来捕捉致命的错误?

正如这个答案所示,你可以使用register_shutdown_function()来注册一个callbackerror_get_last()来检查error_get_last()

您仍然必须pipe理由有问题的代码生成的输出,不pipe是由@闭嘴 )操作符还是ini_set('display_errors', false)

 ini_set('display_errors', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo 'Caught at shutdown'; } }); try { while(true) { $data .= str_repeat('#', PHP_INT_MAX); } } catch(\Exception $exception) { echo 'Caught in try/catch'; } 

运行时, Caught at shutdown输出Caught at shutdown 。 不幸的是,不会引发ErrorExceptionexception对象,因为致命错误触发了脚本终止,随后仅在closuresfunction中捕获。

您可以在closuresfunction中查看$error数组,以获取有关原因的详细信息,并作出相应的响应。 一个build议可能是重新发回请求对您的Web应用程序( 在不同的地址,或与当然不同的参数 ),并返回捕获的响应。

我build议保持error_reporting()高( 值为-1 ),并使用( 像其他人所build议的 )error handling的其他一切与set_error_handler()ErrorException

如果在发生这种错误时需要执行业务代码(logging,为将来的debugging,电子邮件等备份上下文),注册closuresfunction是不够的:应该以某种方式释放内存。

一种解决方法是在某处分配一些紧急内存:

 public function initErrorHandler() { // This storage is freed on error (case of allowed memory exhausted) $this->memory = str_repeat('*', 1024 * 1024); register_shutdown_function(function() { $this->memory = null; if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING)))) { // $this->emergencyMethod($err); } }); return $this; }