如何从致命错误“允许的内存大小耗尽”中恢复

时间:2010-02-23 14:32:33

标签: php error-handling fatal-error

您是否知道从PHP致命错误中恢复的任何解决方案:“允许的内存大小......已用尽

我有一个关闭函数,当出现致命错误时调用该函数。此函数从中创建一个ErrorException,并记录它。

问题是:当没有更多可用内存时,它无法记录错误(我使用Zend Framework通过FirePHP登录Firebug)。

所以我的意思是“如何从中恢复”,是如何执行基本错误日志,让Zend Framework发送Headers,以便记录错误(在我的Firebug中) case)和其他任何错误一样吗?

由于

7 个答案:

答案 0 :(得分:9)

此错误是致命错误 - 这意味着您无法从中恢复。如果PHP达到内存限制,它将无法再分配任何内存来创建异常以及执行它所需的任何其他内存。

还有另一种类型的错误 - “可捕获的致命错误”,顾名思义,可以在try / catch中捕获,但不幸的是内存大小分配不是其中之一。

答案 1 :(得分:8)

if((memory_get_usage() / 1024 /1024) < 70)

我只是将memory_get_usage除以1024平方,将其与'正常'兆字节值'70'进行比较。

我在for循环中遇到了内存问题,并编写了这个简单的if语句,以防止我的脚本引发致命错误。另外,我操作的服务器不允许我修改内存限制(在一些云产品中通常就是这种情况,比如openshift或像dreamhost这样的大型网络主机。)我没有注意到任何严重的性能下降(在php 5.3中,这可能会处理与php 4.x或5.x略有不同的函数......无论如何,给出致命错误的脚本的性能含义超过了函数调用可能强制的任何开销。并且还会阻止消耗所有可用内存的失控脚本。

许多人可能会争辩;哦,嘿,你的软件没有优化。是。你也许是对的;但是对于复杂的数据集,你只能在需要为它投入更多内存之前挤出这么多的性能;并且追踪ajax流中的内存错误可能非常令人沮丧;特别是当您不确定日志文件的位置时。

答案 2 :(得分:4)

定制错误处理的常规方法是通过

set_error_handler - 设置用户定义的错误处理函数

此功能的文档状态(强调我的):

  

使用用户定义的函数无法处理以下错误类型: E_ERROR ,E_PARSE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,以及调用set_error_handler()的文件中引发的大部分E_STRICT。

所以,它不会定期运作,但你可以尝试

从PHP7开始,错误和异常是Throwables,因此您可以尝试/捕获它们:

答案 3 :(得分:2)

默认情况下,PHP错误会发送到您的apache错误日志/path/to/apache/logs/error.log,您可以在那里看到它。

答案 4 :(得分:2)

知道一个未经测试的技巧,我很乐意知道它是否有帮助。首次注册关闭函数时分配一些全局变量,并在首次执行关闭函数代码时释放它。然后,您可以有足够的内存来创建Exception对象。请告诉我它是否有效,请在此处发布代码。

答案 5 :(得分:1)

我能想到的是,当你进行内存密集型操作时,你会定期手动查询memory_get_usage()(例如每次循环迭代),并在它过了一些时转出你的标题/错误故障安全值低于脚本限制。它会减慢你的脚本速度,但至少你会得到回报。

或者,您可能无法执行此操作,使用exec将基于CLI的脚本作为基于Web的内容调用来运行内存密集型内容。 CLI部分可能会失败,但Web部件将能够报告它。

答案 6 :(得分:1)

这对我来说很好:

try {
    ini_set('memory_limit', (ini_get('memory_limit')+1).'M');
} catch(Exception $e) {}

这假设您的内存限制采用123M格式。