如何避免“记忆......在自定义错误处理程序中使用 debug_backtrace() 时出现“exhausted”错误?

How to avoid “memory … exhausted” error when using debug_backtrace() in custom error handler?

提问人:Nate 提问时间:7/24/2014 最后编辑:Nate 更新时间:11/3/2016 访问量:9911

问:

我为我的网站编写了一个错误处理程序,如下所示:

function errorHandler($number, $string, $file, $line, $context, $type = '') {
// save stuff in DB
}

我是这样注册的:

set_error_handler('errorHandler', E_ALL);

我将所有传递的变量保存在数据库中,以及一个回溯跟踪来帮助我调试问题:

print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT), true)

问题是我有时会收到此错误:

允许的内存大小已耗尽 134217728 字节(尝试分配 30084081 个字节)

错误处理程序在出现上述错误时运行的原因是,我在创建 Amazon S3 对象(来自他们的 PHP AWS 库)后尝试使用未定义的变量。我假设,因为 Amazon AWS 库非常庞大,以至于回溯正在提取大量数据,这会导致内存不足错误 (?)。

我想在可能的情况下包含回溯以帮助调试,但是如何防止调用函数导致致命错误(在我的错误处理程序中,这有点讽刺..)?debug_backtrace()

php 错误处理 custom-error-handling

评论

0赞 Charlie Schliesser 7/29/2014
查看 stackoverflow.com/questions/5175969/...
0赞 Nate 7/29/2014
@CharlieS我已经看到了,但不幸的是,那里没有提出有效的解决方案。

答:

3赞 Cedric 7/26/2014 #1

您可以为您的debug_backtrace设置限制。

print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 50), true);

PHP debug_backtrace

评论

5赞 Nate 7/27/2014
好主意,但不幸的是它没有用。我什至尝试更改为,但它仍然内存不足。501
0赞 ToxaBes 7/29/2014 #2

尝试增加内存限制:

ini_set("memory_limit","256M");
print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT), true);

评论

0赞 Nate 7/30/2014
这可能会起作用,但我认为对于生产服务器来说,这不是一个现实的解决方案,原因有两个:1)我认为出于安全原因被禁用,2)如果它真的在发生错误时占用那么多内存,那么几个同时发生的错误会耗尽整个服务器的内存。ini_set()
2赞 ToxaBes 7/31/2014
我只是向您展示方法,您可以在 .htaccess/php.ini/etc 中增加内存限制。如果您想使用DEBUG_BACKTRACE_PROVIDE_OBJECT毫无疑问,您应该增加当前内存限制。但是,如果您想在不更改设置的情况下获取调试信息,请使用 $e->getTraceAsString() 如下所述的 edmondscommerce。
12赞 edmondscommerce 7/31/2014 #3

我怀疑你只需要删除DEBUG_BACKTRACE_PROVIDE_OBJECT

可能是您的代码在对象中具有循环引用,这意味着在转储它们时,它会循环直到消耗所有内存。

另一种替代方法是抛出并捕获异常,然后使用它来获取回溯

try{
  throw new Exception();
}catch(Exception $e){
  echo $e->getTraceAsString();
}

http://php.net/manual/en/exception.gettraceasstring.php

或者,如果您需要冗长,请尝试 print_r($e->getTrace());

http://php.net/manual/en/exception.gettrace.php

评论

0赞 Barkermn01 6/19/2019
当失败应该被标记为答案时,这非常有效debug_backtrace()
1赞 King lotus 8/1/2014 #4

首先检查它是否真的是令人筋疲力尽的记忆。 一旦我遇到这个错误,我就追溯到一个无限循环。

由于您的服务器不允许ini_set,我建议您在本地系统复制它并将内存增加到 1GB 并检查内存是否仍然耗尽,这是一个无限循环。

1赞 Xildatin 8/2/2014 #5

可能不是最好的答案,但您是否考虑过使用 var_dump 而不是 print_r?var_dump只下降了几个嵌套级别,因此 EdmondsCommerce 提到的循环引用问题不会导致您的内存耗尽。

评论

0赞 Joel Mellon 6/17/2016
这非常有效。它可能不会给你带来你需要的一切,但它能给你一些东西,这总比没有和超时要好。
1赞 Jānis Elmeris 11/6/2017
var_dump除非安装了 XDebug 扩展,否则会一直下降。;)
7赞 Tyler V. 11/3/2016 #6

如果可能的话,我会建议用DEBUG_BACKTRACE_PROVIDE_OBJECTDEBUG_BACKTRACE_IGNORE_ARGS

http://php.net/manual/en/function.debug-backtrace.php