【问题标题】:destructing an object with references to itself使用对自身的引用来解构对象
【发布时间】:2011-10-29 18:03:44
【问题描述】:

在调试一段耗尽内存的代码时,我发现了一个非常有趣的问题,最重要的是我不知道如何解决它。

该应用程序大致由一个Survey 对象组成,其中包含许多Question 对象。 Question 对象包含对他们所在调查的引用,例如,这对于能够从其他 Questions 获取答案是必需的。


以下循环导致内存溢出:

foreach ( $survey_ids_arr as $survey_id ) {
    $Survey = new Survey( $survey_id );
}

Survey 构造函数中并没有发生真正奇怪的事情;

  • 从数据库中获取其属性
  • 从数据库中获取所有问题的属性
  • 为每个问题创建一个 Question 对象(传递对 $this 的引用)
  • 将所有 Question 对象添加到内部数组中

通过查看代码,您会说在每次迭代中,对象都会从内存中清除,因为 $Survey 变量被覆盖了。正确的??错了:)

随着脚本循环,内存正在堆积——添加memory_get_usage() 调用表明调查对象使用的内存没有按预期释放,此时另一个对象被分配给$Survey 变量.即使在循环结束时调用unset( $Survey ) 也不会释放内存。


罪魁祸首是对 $this 的引用,这些引用在创建时传递给 Question 对象。这些引用阻止从内存中清除对象 - 正如 php.net 上的手册所述:

一旦删除了对特定对象的所有引用,就会调用析构函数

所以阻止对象被清理的是它对自身的引用。不错吧? :)

所以,问题是我的对象是一个内存杀手。不幸的是,我想不出一个解决方案(除了编写一个丑陋的方法来清除问题并从循环中调用它)。 Survey 中的析构函数不是一个选项;如上所述,这不被称为因为问题对象仍然有引用。

有什么想法吗?一定有人已经遇到过这个问题 - 包含父对象的子对象并不是一个不常见的架构,是吗?

【问题讨论】:

  • 问题是你设计中的一个悖论:你想防止对象从内存中被清除但又想清除它?
  • 这个问题在 php 5.3 中得到解决。你用的是什么 PHP 版本?
  • 你说得对,J0HN,我刚刚找到了错误报告! bugs.php.net/bug.php?id=33595
  • 经验法则:始终使用当前版本的 PHP。 PHP 5.2 已经在几个月前停产了。它不包含很多有用的功能。不要使用它。
  • 我同意 - 这是同事的机器,我什至不知道它运行的是 5.2 ;)

标签: php oop destructor


【解决方案1】:

所以,这里是答案:切换到 PHP 5.3,因为这个问题已经出现在 resolved 中。如果您必须使用 PHP GC收集它们。

附:也可能对某些人有用,Doctrine 1.2 在模型中有这样的链接,因此它容易发生内存泄漏,尤其是当您从数据库中获取大量实体时。如果您遇到此问题,请尝试 (1) 减少获取的实体数量(例如,将水合物作为数组),(2) 使用原始 sql 请求处理实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-18
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多