I recently asked a question about overwriting objects and memory management in Perl. One of the answers I received notified me that I may have an issue with a script I recently wrote.
I have a script with some very complex data structures that have many parent->child / child->parent
relationships. This also means that there are many objects that have cyclic references. According to this answer, cyclic references can "trick" Perl's reference counting mechanism and cause memory leaks if they are not dealt with properly.
Example of a cyclic reference:
+-----------------------------------------------------+
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$parent -->+============+ [ Hash ] |
[ ] +==========+ |
[ children --->[ Array ] |
[ ] [ ] |
+==========+ [ 0: ---------+ |
[ ] | |
+==========+ | |
| |
+--------------------------------------------------+ |
| |
+-->+============+ +==========+ |
[ Reference ----->[ Blessed ] |
$child --->+============+ [ Hash ] |
[ ] |
[ parent: ----------------------+
[ ]
+==========+
(Disclaimer -- this is not my epic artwork -- Thanks @Ikegami for this sweet ASCII diagram!)
Problem: Each object has a reference to the other . . . this means that once $parent
and $child
go out of scope, Perl's reference counter still thinks that a reference to each object exists so the memory is never freed. You wind up with two objects in memory with no way to access the data of either of them!
My question is: What is the proper way to deal with cyclic references to ensure Perl handles its cleanup properly? How do you make sure Perl doesn't leave any pieces behind when all external references to a self-referential object are eliminated?