note 105368 added to language.oop5.decon

From: Date: Fri, 12 Aug 2011 11:17:37 +0000
Subject: note 105368 added to language.oop5.decon
Groups: php.notes 
Request: Send a blank email to php-notes+get-182440@lists.php.net to get a copy of this message
Be aware of potential memory leaks caused by circular references within objects. The PHP manual states "[t]he destructor method will be called as soon as all references to a particular object are removed" and this is precisely true: if two objects reference each other (or even if one object has a field that points to itself as in $this->foo = $this) then this reference will prevent the destructor being called even when there are no other references to the object at all. The programmer can no longer access the objects, but they still stay in memory. Consider the following example: <?php header("Content-type: text/plain"); class Foo { /** * An indentifier * @var string */ private $name; /** * A reference to another Foo object * @var Foo */ private $link; public function __construct($name) { $this->name = $name; } public function setLink(Foo $link){ $this->link = $link; } public function __destruct() { echo 'Destroying: ', $this->name, PHP_EOL; } } // create two Foo objects: $foo = new Foo('Foo 1'); $bar = new Foo('Foo 2'); // make them point to each other $foo->setLink($bar); $bar->setLink($foo); // destroy the global references to them $foo = null; $bar = null; // we now have no way to access Foo 1 or Foo 2, so they OUGHT to be __destruct()ed // but they are not, so we get a memory leak as they are still in memory. // // Uncomment the next line to see the difference when explicitly calling the GC: // gc_collect_cycles(); // // see also: http://www.php.net/manual/en/features.gc.php // // create two more Foo objects, but DO NOT set their internal Foo references // so nothing except the vars $foo and $bar point to them: $foo = new Foo('Foo 3'); $bar = new Foo('Foo 4'); // destroy the global references to them $foo = null; $bar = null; // we now have no way to access Foo 3 or Foo 4 and as there are no more references // to them anywhere, their __destruct() methods are automatically called here, // BEFORE the next line is executed: echo 'End of script', PHP_EOL; ?> This will output: Destroying: Foo 3 Destroying: Foo 4 End of script Destroying: Foo 1 Destroying: Foo 2 But if we uncomment the gc_collect_cycles(); function call in the middle of the script, we get: Destroying: Foo 2 Destroying: Foo 1 Destroying: Foo 3 Destroying: Foo 4 End of script As may be desired. NOTE: calling gc_collect_cycles() does have a speed overhead, so only use it if you feel you need to. ---- Server IP: 69.147.83.197 Probable Submitter: 217.64.124.225 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.decon.php Edit -- https://master.php.net/note/edit/105368 Del: integrated -- https://master.php.net/note/delete/105368/integrated Del: useless -- https://master.php.net/note/delete/105368/useless Del: bad code -- https://master.php.net/note/delete/105368/bad+code Del: spam -- https://master.php.net/note/delete/105368/spam Del: non-english -- https://master.php.net/note/delete/105368/non-english Del: in docs -- https://master.php.net/note/delete/105368/in+docs Del: other reasons-- https://master.php.net/note/delete/105368 Reject -- https://master.php.net/note/reject/105368 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#182440) next »