如何从致命错误“允许的内存大小耗尽”中恢复
您知道从 PHP 致命错误:“允许的内存大小...耗尽”中恢复的任何解决方案吗?
我有一个在出现致命错误时调用的关闭函数。该函数从中创建一个 ErrorException 并记录它。
问题是:当没有更多可用内存时,它无法记录错误(我通过 FirePHP 和 Zend Framework 登录 Firebug)。
所以我所说的“如何从中恢复”的意思是如何执行基本的错误日志,并让 Zend Framework 发送标头,以便将错误记录为(在我的情况下在 Firebug 中)还有其他错误吗?
谢谢
Do you know any solution to recover from the PHP fatal error : "Allowed memory size ... exhausted"
I have a shutdown function that is called when a fatal error appear. This function create an ErrorException from it, and logs it.
The problem is : when there is no more memory available, it can't log the error (I log in Firebug, via FirePHP, with Zend Framework).
So what i mean by "how to recover from it", is how to perform basic error log, and let Zend Framework send the Headers, so that the error is logged (in Firebug in my case) as any other error ?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我只是将 memory_get_usage 除以 1024 的平方,将其与“正常”兆字节值“70”进行比较。
我在 for 循环中遇到了 php 的内存问题,并编写了这个简单的 if 语句来防止我的脚本引发致命错误。此外,我正在操作的服务器不允许我修改内存限制(在某些云产品(如 openshift 或大型 Web 主机(如 dreamhost))中经常出现这种情况。)我并没有真正注意到任何严重的性能下降(在 php 5.3 中,它处理此类函数的方式可能与 php 4.x 或 5.x 略有不同......无论如何,脚本给出致命错误的性能影响超过了函数调用可能强制的任何开销,并且还会阻止。 。
许多人可能会争论,哦,嘿,你的软件没有优化,是的,但对于复杂的数据集,你只能挤出这么多的性能,然后才需要投入更多的内存 在 ajax 流程中查找内存错误可能会非常令人沮丧,尤其是当您不确定日志文件在哪里时。
I simply divide the memory_get_usage by 1024 squared to compare it to a 'normal' megabyte value of '70'.
I ran into memory problems with php inside a for loop and wrote this simple if statement to prevent my script from setting off a fatal error. In addition, the server I was operating on didn't allow me to modify the memory limit (this is often the case in some cloud offerings like openshift or large web hosts like dreamhost.) I didn't really notice any serious performance degradations (in php 5.3 which may handles functions such as this slightly differently than php 4.x or 5.x... at any rate the performance implication of a script giving a fatal error outweighs any overhead the function call may force. And would also prevent a runaway script from consuming all available ram.
Many may argue; oh hey your software isn't optimized. Yes. You're probably right; but with complex data sets you can only squeeze so much performance out before you need to throw more memory at it; and hunting down memory errors in an ajax flow can be very frustrating; especially when you aren't sure where your log files are.
此错误是致命错误 - 这意味着您无法从中恢复。如果 PHP 达到了内存限制,它将无法分配更多内存来创建异常以及执行执行所需的任何其他内存。
还有另一种类型的错误 - “可捕获的致命错误”,顾名思义,可以在 try/catch 中捕获,但不幸的是内存大小分配不是其中之一。
This error is a fatal error - that means you cannot recover from it. If PHP has hit it's memory limit, it won't be able to allocate any more memory to create your exception and any other memory it needs to carry on its execution.
There is another type of error - "catchable fatal error" which as the name suggests, can be caught in a try/catch, but unfortunately the memory size allocation is not one of them.
自定义错误处理的常规方法是通过
set_error_handler< /code>
— 设置用户定义的错误处理函数
该函数的文档状态(强调我的):
所以,它不会经常工作,但你可以尝试
从 PHP7 开始,错误和异常都是 Throwables,因此您可以尝试/捕获它们:
The regular way to customize error handling is through
set_error_handler
— Sets a user-defined error handler functionThe docs for this function state (emphasis mine):
So, it won't work regularly, but you can try
register_shutdown_function
As of PHP7, Errors and Exceptions are Throwables, so you can try/catch them:
这对我来说效果很好:
假设您的内存限制采用
123M
格式。This worked fine for me:
This assumes your memory limit is in the format
123M
.PHP 错误默认发送到您的 apache 错误日志
/path/to/apache/logs/error.log
,您可以在那里看到它。PHP errors are sent by default to your apache error log
/path/to/apache/logs/error.log
and you can see it there.我有一个未经测试的技巧的想法,我很高兴知道它是否有帮助。在第一次注册关闭函数时分配一些全局变量,并在第一次执行关闭函数的代码时释放它。然后您可能有足够的内存来创建 Exception 对象。让我知道它是否有效,并请在此处发布代码。
Got an idea for an untested trick and I'd be happy to know if it helped. Allocate some global variable when you first register the shutdown function and release it when the shutdown function's code is first executed. You may then have sufficient memory to create the Exception object. Let me know if it worked and please publish the code here.
我能想到的是,当您进行内存密集型操作时,您会定期(例如每次循环迭代)手动查询
memory_get_usage()
,并在发生时转储标头/错误超过某个低于脚本限制的故障安全值。它会大大减慢你的脚本速度,但至少你会得到一些回报。或者,您可能无法执行此操作,通过使用 exec 从基于 Web 的内容中调用基于 CLI 的脚本来运行内存密集型内容。 CLI 部分可能会崩溃,但 Web 部分将能够报告该情况。
One I can think of is that you when you're doing your memory intensive operation you manually query
memory_get_usage()
on a regular basis (e.g. every loop iteration) and dump out your headers/error when it goes over some failsafe value which is below the script limit. It will slow your script down a lot, but at least you'll get something back.Or, and you may not be able to do this, run the memory intensive stuff as a CLI-based script called from inside your web-based stuff by using exec. The CLI part might fall over, but the web part will be able to report on it.
我刚刚发现,对于我的情况,如果用大 int 键填充数组(例如 83253143401),请将它们转换为 String。否则 PHP 将初始化第一个元素为 83253143400 的空数组,甚至 2Gb 内存也不够。
I just have found, for my case, if you fill an array with big int keys (83253143401 for example), cast them to String. Otherwise PHP will init empty array with 83253143400 first elements, and even 2Gb of memory will be not enough.