In Nicholas Zakas' book, he explains the problem of circular referencing when using reference counting for garbage collection in Javascript. He uses the following example:
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
explaining that the two objects will never have the memory allocated to them freed since they have two references to them inside the function. I would like some clarification of how this works.
Clearly, there are two references to each object. The first object has both objectA
and objectB.anotherObject
pointing to it. The situation is analogous for the second object. So the reference count for each object is 2. But what happens when the function is exited? This isn't really described in the book. He says that the reference count is decremented whenever a reference to the value is overwritten with another value. I think this means:
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
objectA.someOtherObject = objectA; //<-- that if I were to do this,
//the reference count of the second object (B)
//would become 1, and 3 for the first object (A).
}
But what happens when the function exits? As far as I understand, both objectA
and objectB
and their respective properties that reference each other will be destroyed, and thus, the two objects' reference counts will be decremented by 2. I don't see the "circular reference problem" that Zakas talks about. Could somebody explain what he's trying to say?
As far as I understand, both objectA and objectB and their respective properties that reference each other will be destroyed.
No. The local variables objectA
and objectB
will be destroyed (because the function scope ends and no closures reference these variables). That means the reference counts in the objects that were referenced by the variables each get decremented by 1.
If the object's reference count was 0, the object would get destroyed and all other things it references would get their count decremented. But the counts of the objects still are 1
each - they still reference each other -, and nothing gets destroyed.
The "problem" with reference counting and "circular" reference comes about when allocated objects contain references to other objects, but are otherwise unreferenced by active allocations. That is, there are cliques in the overall reference graph of items that are not active but which nevertheless contain references to other non-active items.
In your example code, when that function exits there are no active references to the two allocated objects, but the objects reference each other so the reference counts are not 0. The local variables objectA
and objectB
will disappear at the exit of the function (because the closure is itself garbage, at that point), but the internal references the objects hold keep their reference counts greater than zero.
It's not an unsolvable problem, but it complicates the otherwise simple approach of reference counting as a garbage collection technique.
Note that there's no rule or specification that insists JavaScript implementations use any particular garbage collection technique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With