php - 使用对自身的引用销毁对象

标签 php oop destructor

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

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


以下循环导致内存溢出:

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

在 Survey 构造函数中并没有发生任何奇特的事情;

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

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

当脚本通过循环时,内存正在堆积 - 添加 memory_get_usage() 调用显示 Survey 对象使用的内存没有按预期释放,此时另一个对象正在释放分配给 $Survey 变量。即使在循环结束时调用 unset( $Survey ) 也不会释放内存。


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

The destructor method will be called as soon as all references to a particular object are removed

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

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

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

最佳答案

所以,这里是答案:切换到 PHP 5.3,因为这个问题已经 resolved在里面。如果您必须使用 < 5.3.0 的 PHP,您有责任释放在循环引用中捕获的对象。一种可能的方法是引入特殊方法,该方法将剥离指向子对象的链接,以允许它们被 GC

收集

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

关于php - 使用对自身的引用销毁对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7107258/

相关文章:

oop - 依赖注入(inject)容器 - 工厂模式

java - 如何将Java接口(interface)代码移植到C++抽象基类中?

c++ - 我需要清理非指针数据成员吗?

c++ - 当对象在堆栈上声明时,你能保证析构函数的顺序吗?

c++ - C++在哪里调用析构函数?

php - 如何使用php将iPhone输入的奇数字符转换为单个字符

php - 从数组中删除重复值

java - Setter 没有为 java 对象设置值

mysql 表中的 PHP echo 类别名称

php - WordPress:如何在任何管理页面上显示元数据框?