gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 13:28:48 27 4
gpt4 key购买 nike

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

该应用程序大致由一个 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com