Look at the following code, which is meant to be a stripped-down and simplified version of my real code:
Class DatabaseMgr
DatabaseMgr instproc openDatabase {} { Database [self]::db }
Class Database
Database instproc init {} { puts "init [self]" }
Database instproc destroy {} { puts "destroy [self]" }
DatabaseMgr dbmgr
dbmgr openDatabase
dbmgr::db info class dbmgr::db destroy dbmgr::db info class
The second call to "info class" should fail but doesn't. That's because the object isn't actually destroyed. (In my real code the objects have dynamically generated names; I used the static names to simplify the example.)
The above style is similar to the style of code used in xoRBAC (eg, factories & self-destruction) so I'd be surprised if it too wasn't leaking objects.
After the above code run this code:
dbmgr info class dbmgr destroy dbmgr info class
Now both dbmgr and dbmgr::db are destroyed--but note that the "destructor" gets called twice at this point!
By contrast, the following example (which also uses nested/aggregated objects) succeeds (which is to say that the second call to "info class" fails):
Object instproc doSomethingAndDie {} {[self] destroy} set xxx [Object new] set yyy [Object new -childof $xxx] set zzz [Object new -childof $yyy] puts "[$yyy info class]" $yyy doSomethingAndDie puts "[$yyy info class]"