Home > Blockchain >  The PHP unset doesn't clear the reference completely
The PHP unset doesn't clear the reference completely

Time:08-30

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 and Foo::$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 the refcount of it. This can be proved using debug_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 the refcount 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);

Online Demo

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.

  • Related