在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
。 不幸的是,不会引发ErrorException
exception对象,因为致命错误触发了脚本终止,随后仅在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; }
你可以通过使用这个函数获得已经被进程消耗的内存的大小memory_get_peak_usage文档在http://www.php.net/manual/en/function.memory-get-peak-usage.php我认为它会如果可以添加一个条件来redirect或停止进程,在进程几乎达到内存限制之前,将会更容易。; 🙂