I have a simple class and assign its instance to its static variable. When I unset the instance, not sure why it doesn't actual release the memory.
class Foo {
public static $app;
public function __construct() {
self::$app = $this;
}
}
$foo = new Foo;
unset($foo);
var_dump($foo);
var_dump(Foo::$app);
Result:
Warning: Undefined variable $foo in /var/www/index.php on line 16
NULL object(Foo)#1 (0) { }
Obviously, the static $app point to the itself instance, we have unset the instance but doesn't really clean the memory for this variable. Why did it happen? Are the instance of the $app and the $foo different ones?
CodePudding user response:
$foo
andFoo::$app
point to the same object as you desire. Any changes in terms of object properties will reflect either way if you do it.This is because they point to the same copy in the memory as expected. However, PHP maintains a
refcount
indicating how many references to that memory location is present.So, when you use
unset($foo);
, it doesn't garbage collect that memory location(and the value inside it), but rather just decreases therefcount
of it. This can be proved usingdebug_zval_dump
and PHP achieves the refcount maintenance using copy on write mechanism as mentioned in the linked doc.Hence, unsetting
$foo
doesn't destroy the object itself but rather just therefcount
and removes the variable from memory since the object still holds other references.
Snippet:
<?php
class Foo {
public static $app;
public function __construct() {
self::$app = $this;
}
}
$foo = new Foo;
var_dump($foo === Foo::$app);
debug_zval_dump(Foo::$app);
$foo = 90;// variable modified, copy on write mechanism done internally for Foo::$app, refcount modified
debug_zval_dump(Foo::$app);
CodePudding user response:
You've only unset a reference to an object of class Foo
, and that object will get garbage-collected next time garbage collector runs.
Classes, once loaded, live in the memory until request is terminated, and so will their static properties. If they hold a pointer to an object, that object won't be garbage-collected. If you want to garbage-collect Foo::$app
, you'll need to unset it too.