PHP and the story of reference counting
Today I want to talk about a very specific situation, where PHP’s reference management simply fails. Imagine the follow piece of code (I’ve stripped some of the method bodies to simplify the example):
class Connection { public function connect(); public function disconnect(); public function __destruct() { $this->disconnect(); } } class MySpecialConnectionAggregator { private $oConnection; public function __construct() { $this->oConnection = new Connection(); $this->oConnection->connect(); }
We have a class called „Connection“ and a aggregator for that class named „MySpecialConnectionAggregator“.
I would have expected, that a call of unset() on the MySpecialConnectionAggregator removes the instance of MySpecialConnectionAggregator and the encapsulated instance of Connection from the userland calling the __destruct() method of the Connection
What do you think? *Beeeep* … Wrong 😉 It is NOT removed and remains as a dead reference in the memory.
You have to implement something like this:
// ... we are in class MySpecialConnectionAggregator public function __destruct() { unset($this->oConnection); }
We have a class called „Connection“ and a aggregator for that class named „MySpecialConnectionAggregator„.
I would have expected, that a call of unset() on the MySpecialConnectionAggregator removes the instance of MySpecialConnectionAggregator and the encapsulated instance of Connection from the userland calling the __destruct() method of the Connection
What do you think? *Beeeep* … Wrong 😉 It is NOT removed and remains as a dead reference in the memory.
You have to implement something like this:
// ... we are in class MySpecialConnectionAggregator public function __destruct() { unset($this->oConnection); }
By the way: This is „fixed“ in PHP 5.3 and up, as the garbage collection of 5.3 works better than in 5.x.