分类分类
更新时间:2026-04-09 13:23:37作者:zhao
PHP对象相互引用的内存溢出实例分析,是PHP5.3以下版本中常见的一个bug,文中给出了解决方法
通常来说使用脚本语言最大的好处之一就是可利用其拥有的自动垃圾回收机制来释放内存。你不需要在使用完变量后做任何释放内存的处理,因为这些PHP会帮你完成。
当然,我们可以按自己的意愿调用 unset() 函数来释放内存,但通常不需要这么做。
不过在PHP里,至少有一种情况内存不会得到自动释放,即便是手动调用 unset()。详情可考PHP官网关于内存泄露的分析.
问题症状如下:
如果两个对象之间存在着相互引用的关系,如“父对象-子对象”,对父对象调用 unset()不会释放在子对象中引用父对象的内存(即便父对象被垃圾回收,也不行)。
是不是有些糊涂了?我们来看下面的这段代码:
运行这段代码,你会看到内存使用率越来越高越来越高,直到用光光。
对大部分PHP程序员来讲这种情况不算是什么问题。可如果你在一个长期运行的代码中使用到了一大堆相互引用的对象,尤其是在对象相对较大的情况下,内存会迅速地消耗殆尽。
Userland解决方案
虽然有些乏味、不优雅,但之前提到的 bugs.php.net 链接中提供了一个解决方案。
这个方案在释放对象前使用一个 destructor 方法以达到目的。Destructor 方法可将所有内部的父对象引用全部清除,也就是说可以将这部分本来会溢出的内存释放掉。
注意那个新增的Foo::__destruct()方法,以及在释放对象前对 $foo->__destruct() 的调用。现在这段代码解决了内存使用率一直增加的问题,这么一来,代码就可以很好的工作了。
PHP内核解决方案
为什么会有内存溢出的发生?我对PHP内核方面的研究并不精通,但可以确定的是此问题与引用计数有关系。
在 $bar 中引用 $foo 的引用计数不会因为父对象 $foo 被释放而递减,这时PHP认为你仍需要 $foo 对象,也就不会释放这部分的内存。原理大致如此。
通俗的来说,大体意思是:一个引用计数没有递减,所以一些内存永远得不到释放。
此外在前面提到的 bugs.php.net 链接中指出了修改垃圾回收的过程将会牺牲极大的性能,需要读者对此注意。
与其改变垃圾回收的过程,为什么不用 unset() 对内部对象做释放的工作呢?(或者在释放对象的时候调用 __destruct()?)
也许PHP内核开发者可以在此或其他地方,对这种垃圾回收处理机制做出修改。
相关
假面骑士泽兹变身模拟器休闲益智51.91 Mv1.00.302026-04-09
下载餐车厨师烹饪游戏苹果版模拟游戏327.2 Mv8.682026-04-09
下载最终幻想7永恒危机ios版角色游戏1.5Gv3.6.02026-04-09
下载英勇之地苹果版射击游戏2.6Gv4.20.22026-04-09
下载森空岛ios版手游辅助163.8 Mv1.55.02026-04-09
下载呱呱AI英语(儿童英语启蒙平台)学习办公334.6 MBv1.3.32026-04-09
下载附近先遇2026下载社交通讯86.0 MBv1.1.412026-04-09
下载变种人吃了我的胡萝卜解锁关卡(冒险童话游戏)趣味娱乐1.20 GBv1.032026-04-09
下载重返战场:特战精英2026下载趣味娱乐99.0 MBv4.12026-04-09
下载手机计算器免费(多功能计算工具)生活服务54.0 MBv1.0.82026-04-09
下载风筝飞呀最新手机版社交通讯64.2 MBv1.1.92026-04-09
下载万用智能点击器(自动化点击工具)生活服务50.7 MBv1.0.02026-04-09
下载










