Php 如何调试泄漏引用?

Php 如何调试泄漏引用?,php,php-7.0,Php,Php 7.0,我们有一个复杂的PHP程序正在泄漏一个对象。是否有任何方法可以在每次引用计数增加时获得回调,以便我可以记录所有引用位置的堆栈跟踪?该程序正在使用RAII编程模型,该泄漏导致析构函数的运行比预期的要晚得多(在进程退出的最坏情况下) 代码基本上是 while (!$done) { # create database connection for each try (serializable transactions with fallback servers) $connection = .

我们有一个复杂的PHP程序正在泄漏一个对象。是否有任何方法可以在每次引用计数增加时获得回调,以便我可以记录所有引用位置的堆栈跟踪?该程序正在使用RAII编程模型,该泄漏导致析构函数的运行比预期的要晚得多(在进程退出的最坏情况下)

代码基本上是

while (!$done)
{
  # create database connection for each try (serializable transactions with fallback servers)
  $connection = ...;
  $transaction = $connection->newTransaction(...);
  try
  {
    doStuffWithTransaction($transaction);
    $transaction->commit();
    $done = true;
    ...; # additional best-effort cleanup routines
  }
  catch (TransactionMustRetry $e)
  {
    $transaction->rollback();
  }
  catch (\Throwable $e)
  {
    ...
  }
  $connection->disconnect();
}
如果
doStuffWithTransaction()
中的某个嵌套例程抛出了
\Throwable
,则
$transaction
应该自动回滚。但是,
$transaction
在调用此函数之前具有refcount=2,在捕获
\Throwable
时具有refcount=3,这导致回滚不会自动回滚


如何判断哪些代码获得了对$transaction的引用?

您是否查看了
doStuffWithTransaction()
?是的,它会递归地创建10000多个对象,执行各种操作。调试它为什么会在某处泄漏引用并不容易。您可以为事务创建一种代理。创建一个代理类,该类实现
$transaction
的每个方法,并将调用委托给实际事务。捕获可丢弃项后,可以删除代理中对事务的引用,从而强制应用程序中的refcount为0。如果泄漏的引用是一个语句/查询/等,则这不会起作用。事务本身包含对Transsaction的引用,而我实际上刚刚找到了这个特定问题的原因:变量
$e
在下一个循环迭代中保持活动状态,并包含上一个异常的堆栈。由于堆栈包含方法和函数的参数,因此对
$transaction
缺少的引用嵌套在
$e
中。添加
unset($e)记录异常后立即修复泄漏。然而,我仍然在寻找一种方法来调试这类问题。你是绝对正确的。我找到了任何与查看引用所有者相关的内容,我只能想出一些其他解决方法来解决弱引用:你在
doStuffWithTransaction()
中查找的PDid?是的,它会递归创建10000多个对象,做各种事情。调试它为什么会在某处泄漏引用并不容易。您可以为事务创建一种代理。创建一个代理类,该类实现
$transaction
的每个方法,并将调用委托给实际事务。捕获可丢弃项后,可以删除代理中对事务的引用,从而强制应用程序中的refcount为0。如果泄漏的引用是一个语句/查询/等,则这不会起作用。事务本身包含对Transsaction的引用,而我实际上刚刚找到了这个特定问题的原因:变量
$e
在下一个循环迭代中保持活动状态,并包含上一个异常的堆栈。由于堆栈包含方法和函数的参数,因此对
$transaction
缺少的引用嵌套在
$e
中。添加
unset($e)记录异常后立即修复泄漏。然而,我仍然在寻找一种方法来调试这类问题。你是绝对正确的。我发现任何与查看引用所有者相关的东西,我只能想出一些其他的解决方法来使用弱引用:P