【发布时间】: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