为什么debug_backtrace()有时不包括行号?

时间:2011-01-03 03:57:32

标签: php debugging

我发现有时候debug_backtrace()不包括来电号码。有什么理由可以解决这个问题吗?

提前致谢。

P.S。是的,省略行号的调用是我自己的代码,而不是内部PHP代码。

4 个答案:

答案 0 :(得分:11)

请考虑以下代码:

<?
class BtTest
{
  public function getTheItem()
  {
    var_dump( debug_backtrace( false ) );
    $bt = debug_backtrace( false );
    return $bt[1];
  }

  public function __call( $methodName, $methodArgs )
  {
    return $this->getTheItem();
  }
}

$o = new BtTest();
$bti = $o->test();

assert( 'array_key_exists("function", $bti)' );
assert( 'array_key_exists("line", $bti)' );
assert( 'array_key_exists("file", $bti)' );

以上示例的执行会生成以下输出:

array(3) {
  [0]=>
  array(6) {
    ["file"]=>
    string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
    ["line"]=>
    int(13)
    ["function"]=>
    string(10) "getTheItem"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(0) {
    }
  }
  [1]=>
  array(4) {
    ["function"]=>
    string(6) "__call"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(2) {
      [0]=>
      &string(4) "test"
      [1]=>
      &array(0) {
      }
    }
  }
  [2]=>
  array(6) {
    ["file"]=>
    string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
    ["line"]=>
    int(18)
    ["function"]=>
    string(4) "test"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(0) {
    }
  }
}
PHP Warning:  assert(): Assertion "array_key_exists("line", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 21
PHP Warning:  assert(): Assertion "array_key_exists("file", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 22

第一个回溯项(索引0)间接(通过linefile个项目)表示从getTheItem方法调用__call方法。

第二个回溯项(索引1)表示从某处调用了__call方法(缺少linefile个项目。)

第三个回溯项(索引2)表示从脚本的全局范围调用test方法。

__call方法调用的位置可能在php解释器代码中的某些方法解析代码中。修复它有两种可能性。第二个项目应该引用解释器的源代码文件和行,或者第二个和第三个回溯项目应该合并为一个。我个人更喜欢第二种解决方案,因为解释器的内部结构对我来说并不感兴趣(这就是他们在python的追溯中的表现),但是我知道有时第一种解决方案提供了更明确的跟踪(特别是当它是一个回调时,它是从内部调用。)

左右,似乎负责(或至少维护)debug_backtrace函数代码的开发人员并不认为它是一个bug或者没有简单的方法来解决它。可以使用一些占位符值(例如linefile或甚至 nulls )填充<unknown-file>0项并强调它在文档中。 除非有人成功说服他们这样做,否则你只需要处理代码中的特殊情况。

我上面写的只是为了分享我对函数奇怪行为的理解。如果有人愿意为更好的世界而战,那么这里有一些相关错误报告的链接:

最早的报告来自2003年,所以你不应指望快速修复:)

答案 1 :(得分:4)

我认为这被列为PHP Bug

  

调试回溯显示文件名和   调用脚本的lineno。如果   函数从内部调用   内部函数(可能作为回调)   没有文件名和lineno可以设置。

答案 2 :(得分:1)

无论任何“错误”,“功能”,无论维护PHP的人是什么意思,debug_backtrace()都不会像我期望的那样工作。

这是我的解决方案(它很难看,但它对我有用):

function dbg($msg="")
{
    ob_start();
    debug_print_backtrace(0,1);
    $_ = ob_get_clean();
    list($ignore,$line_number) = explode(':', $_);
    $line_number += 0;

    $backtrace = debug_backtrace(0);
    extract($backtrace[1]);
    echo "<pre>$class::$function($msg) : $line_number</pre>";
}

PHP函数debug_print_backtrace(0,1);会产生这样的东西:

#0 dbg-&gt; ping(290)调用[/path/to/filename.php:290]

因为它只回显了跟踪,所以我必须将ob_get_clean()作为一个字符串。然后我解析它。

在我的实现中,我只想知道调用函数的类,函数,行号和(可选)字符串消息。 debug_backtrace()正确提供类和函数,但不提供行号。这就是为什么我必须从debug_print_backtrace()函数中获取行号。

对于奖励积分....如何调试debug_print_backtrace()函数“知道”行号,但是debug_backtrace()[偶尔]不会,呃??? ......这是一个谜......

答案 3 :(得分:1)

在各种 PHP 版本的 bugs.php.net 上检查了一堆相关问题后,这个问题似乎已经在 PHP 7.0 及更高版本上得到修复,包括 8.0,它总是提供一个“文件”,即使它是假的像从 stdin 评估的代码的“标准输入代码”。