PHP中unset实例后内存未释放的原因及引用分析
实例赋值给自身静态变量后unset无法释放内存的原因解析
问题描述
定义了一个简单的类,并将其实例赋值给自身的静态变量。使用unset销毁该实例后,发现内存并未真正释放,需解析以下问题:
$app与$foo指向的是同一个实例吗?- 为何
unset($foo)后实例内存未被释放?
代码示例
class Foo { public static $app; public function __construct() { self::$app = $this; } } $foo = new Foo; unset($foo); var_dump($foo); var_dump(Foo::$app);
执行结果
Warning: Undefined variable $foo in /var/www/index.php on line 16 NULL object(Foo)#1 (0) { }
原因解析
$app和$foo指向同一个实例
执行$foo = new Foo时,创建了Foo类的实例,$foo变量持有该实例的引用;构造函数中self::$app = $this,$this代表当前创建的实例,因此静态变量Foo::$app也持有同一个实例的引用,二者指向完全相同的对象。PHP引用计数机制导致内存未释放
PHP采用引用计数管理内存:每个对象实例都有一个引用计数器,记录当前有多少个变量/指针指向它。- 创建实例时,
$foo指向它,引用计数为1; - 构造函数中
self::$app = $this,新增一个引用,计数变为2; - 执行
unset($foo)仅销毁$foo变量对实例的引用,引用计数降到1,但静态变量Foo::$app仍持有该实例的引用,计数未到0,PHP垃圾回收机制不会释放该实例的内存。
- 创建实例时,
只有当Foo::$app也被销毁(比如执行unset(Foo::$app)),实例引用计数降到0时,内存才会被真正释放。
内容的提问来源于stack exchange,提问作者Mark Smith
相关产品推荐
相关产品推荐

