** Description ** The [comp.lang.tcl%|%clt%|%] thread, "[http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/6a6853a37b1d95a6%|%Tcl_ObjSetVar2... ,Martin Lembug ,2005-10-12]", and [https://sourceforge.net/tracker/?func=detail&atid=110894&aid=1334947&group_id=10894%|%Bug #1334947%|%] revived the discussion of how to properly manage the reference count of Tcl_Objs. This is an attempt at clarifying the issue, and a roadmap to improving both the core's refCount management as well as the documentation related to the subject. '''1. Categorization''' Joe English writes: ''There are roughly four classes of Tcl_Obj-related library routines:'' * '''Constructors''', which return a fresh Tcl_Obj with 0 refcount; * '''Readers''', which only read the value (but may cause shimmering). * '''Consumers''', which store a new reference to an existing Tcl_Obj, increment the refcount, and arrange to decrement the refcount at some unspecified point in the future. * '''Mutators''', which change the Tcl_Obj and can *only* be used with unshared Tcl_Objs (refcount = 0 or 1). and Donal Fellows adds the category * '''Hairy Monsters'''. Don't give these things refcount==0 objects since they will manipulate the refcount during their processing and might or might not retain a reference. Please note that the same funtion may belong to different categories with respect to different arguments: for example, as currently implemented (up to Tcl8.5a4), the function ''Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags)'' is a Reader wrt part1Ptr and part2Ptr, but a Hairy-Monster wrt newValuePtr. ''([DKF]: It should be noted that there is no guarantee that Tcl_ObjSetVar2 will remain a reader wrt part2ptr; if we ever optimize internal memory management of arrays, that will likely change. This is why knowing which function is what with respect to each argument is hard.)'' '''As a general rule, all Tcl commands should be considered to be Hairy-Monsters wrt the objects in the objv array.''' We hope to improve the documentation wrt to the categorization of the different functions, and also to reduce significantly the population of Hairy-Monsters. As of today, Constructors and Mutators should be properly documented as such. '''2. Rules for dealing safely with the different categories''' Note first that '''Constructors''' are not an issue: there is no Tcl_Obj to manage before you call them. The '''always-safe rules''' are: * '''Mutators''': pass an unshared object (refCount is 0 or 1). In order to respect ''copy-on-write'' semantics, make a copy for your use if you need to modify a shared object, and modify the copy. * '''Readers''', '''Consumers''' and '''Hairy-Monsters''': Tcl_IncrRefCount(objPtr) before calling the library function, Tcl_DecrRefCount(objPtr) on return. This means: assume that every function in the Tcl library that is not a Mutator is a Hairy-Monster. The '''optimal rules''' in terms of performance and code simplicity (but risky in light of incomplete documentation) are: * '''Mutators''': pass an unshared object (refCount is 0 or 1). In order to respect ''copy-on-write'' semantics, make a copy for your use if you need to modify a shared object, and modify the copy. Use ''Tcl_IsShared'' to determine whether you may modify, and ''Tcl_DuplicateObj'' to get the copy. * '''Readers''': if you pass an object with refCount==0, make sure to Tcl_DecrRefCount(objPtr) on return in order not to leak the object. * '''Consumers''': do not worry about reference counts as the consumer takes care of it, including the freeing of unneeded objects. This is ''fire-and-forget''. Passing a fresh Tcl_Obj* to a consumer means you're through using it. * '''Hairy-Monsters''': Tcl_IncrRefCount(objPtr) before calling the library function, Tcl_DecrRefCount(objPtr) on return. ---- **Tcl DOES NOT GARBAGE COLLECT!** I have been trying to understand clearly the rules for Tcl reference counting of objects, and how to properly use the increment and decrement ref count operations. I finally came across a question and answer posting elsewhere, in which Donal K. Fellows clearly explains a very, very, VERY important concept: '''Tcl Does Not Garbage Collect!''' What does this mean for the Tcl extension writer? I can sum it up in a nutshell... if you create an object, and you never pass it back to Tcl as part of another object (eg a list object), or as the result object, it will NOT get freed. You MUST call '''Tcl_DecrRefCount()''' because this is where the memory deallocator gets called... and nowhere else! It goes without saying that for a very experienced programmer such as myself to have to hunt around for this morsel of information means that the documentation for Tcl Objects in the Tcl C reference is ''not explicit enough'' in making this fact crystal clear. It should also be pointed out that calling '''Tcl_DecrRefCount()''' to free an allocated object, without first having called '''Tcl_IncrRefCount(),''' is perfectly OK. The deallocation will happen if the ref count is zero ''or negative''. This can be the case if you must create a new object for the sole purpose of passing it as an argument to another Tcl API, but then have no further use for it. If that bit of code is called over and over, you will end up with many cats and hats wandering in the woods outside Mr. Tesla's mountain laboratory, homeless. I hope someone finds this clarification useful. ** See Also ** * [routines safe for zero-ref objs] * [Tcl_Obj] * [Managing the reference count of Tcl objects] <> Internals