InsertXX() and Ownership



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 16/04/2008 at 14:05, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R9.1 + 
    Platform:   Windows  ; Mac  ;  
    Language(s) :     C++  ;

    ---------
    I may not be entirely awake at the moment, but something that's not entirely clear to me is the subject of ownership after various InsertXX() methods...
    For example, for BaseDocument::InsertObject() the SDK docs say:
    "...The document takes over the ownership of the pointed object."
    ...which seems pretty clear that I don't have to (and in fact should not) Free() or gDelete (or have used an AutoAlloc) on the object pointer I'm passing to that routine (...right?).
    But then you have other classes, like a GeListHead/GeListNode and the various InsertXXX() docs say:
    "...The caller owns the pointed object"
    ...(similar usage also found for things like BaseObject::MakeTag() , BaseObject::MakeVariableTag() , BaseObject::InsertTag() , etc. ).
    One would assume that C4D makes a copy/clone of the passed in pointer, so if I allocated it myself, I should also free it after doing the insertion... right? Except that in the case of BaseObject::MakeTag() and/or BaseObject::MakeVariableTag() , both of those actually create a tag on the object (no need to do an insertion), so clearly the object itself allocated it and knows about it, whereas with BaseObject::InsertTag() , it's more likely that the caller actually allocated the tag.
    Is there some definitive answer in all cases ( "...The caller owns the pointed object" == caller is free to and should in fact free the object if done with it's own internal use of said object) ?
    Thanks,
    Keith



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 16/04/2008 at 16:05, xxxxxxxx wrote:

    My general rules is this:

    Once an object/tag/material/etc. is added to the document (directly or indirectly), it is owned by Cinema 4D (whether or not you allocated it yourself). If you remove it (obj->Remove(), e.g.), then it becomes your responsibility and you must pay child support (and do the Free() yourself).

    ***

    It is usually reasonable to assume that Free() on something with branches or children (objects with tags/tracks/children objects) will Free() them as well.

    Be careful with AutoAlloc<>. The thing only exists within the scope wherein the AutoAlloc<> exists (in a method or block of code). I've never done one of these say for an object that is then permanently added to a document (scary). It is possible that once C4D takes ownership it breaks the scope so that the object continues to exist or that it will disappear at the end of scope causing disastrous behaviour (crashing).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 16/04/2008 at 16:37, xxxxxxxx wrote:

    Yeah, I have generally followed the same rule (once added to document, or some object that's in the document, let C4D worry about it), but I'm just concerned that that may be causing memory leaks - it would be nice to get some clarification on this.
    I'd have to root through my code again to see if I'm doing that in all cases, but I'm kinda in the process of doing just that, which is why the question came up :).  So far, I'm only using AutoAlloc<> in a few places, where I know the object will be of limited scope.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 16/04/2008 at 19:53, xxxxxxxx wrote:

    Methods like MakeTag() only return a pointer to the created /added object. This is not a copy/clone but just a pointer to the object that Cinema 4D created. Although I read these ownership mantras, one has to consider the circumstances similarly.

    Usually if a copy/clone/temp is returned, the docs explicitly state that you must add to document or free the result yourself.

    The two courses otherwise to make explicit determination of these conditions are to run in debug mode or attempt to free the object and see if there is subsequent crashing/erratic behavior.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 17/04/2008 at 02:14, xxxxxxxx wrote:

    Hi,

    as Kuro said, InsertX or MakeX functions result in ownership of Cinema 4D if not explicitly stated otherwise.
    They definetly don´t result in memory leaks, you must be missing something in your code.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 17/04/2008 at 09:45, xxxxxxxx wrote:

    Thanks guys, just keep in mind that part of my goal here is to also point out areas of the SDK docs that may need clarification or fixing (for the record, I'm not experiencing memory leaks, just looking to quell any concern over the possibility).
    Just for clarification/correction to my previous post above, the BaseObject::MakeTag(), BaseObject::MakeVariableTag() and BaseObject::InsertTag() docs are all in fact  correct and do state that the base object (C4D) either owns or takes over ownership (did I mention that I was half asleep when I wrote that first post? :) ).
    I guess the ones I'm really addressing here are:
    GeListHead::InsertFirst()
    GeListHead::InsertLast()
    GeListNode::InsertBefore()
    GeListNode::InsertAfter()
    GeListNode::InsertUnder()
    GeListNode::InsertUnderLast()

    ...In each of the above, the docs say "...The caller owns the pointed object" (the one being passed in / inserted).
    Since the pointer had to come from 'somewhere' (the user/code will already know where), the sentance must be addressing the issue of "who needs to free the object"... and in that context (after an insertion/addition to some C4D maintained scene/document/list), it would only make sense if C4D was cloning the objects.   If it's not, then the docs are - explicitly - wrong and need updating.
    Here's the example user scenerio (from my own experience)...
    - user wants to add LayerObject s to elements of a scene.
    - user searches SDK examples source code, but finds none.
    - user looks up LayerObject in the SDK docs and finds the LayerObject methods, which have allocation and freeing methods, and also sees that it's derived from a BaseList2D (where some additional LayerObject setting/getting methods are found).
    - user also notes that various other elements in question (PolygonObject, Selection Tags, Plugin Tags, etc) are also based on BaseList2D.
    - user puts 2 & 2 together (and comes up with 3, in this case :) ) and allocates some LayerObjects and uses the BaseList2D::SetLayerObject() method to add them to various scene elements.
    - nothing happens.
    - user looks back through the SDK docs and notes  GeListHead *GetLayerObjectRoot(void) as a BaseDocument method..
    - sounds like the BaseDocument needs to track them, so the user looks up GeListHead and finds the above mentioned InsertX method docs.
    - user adds the LayerObjects to the scene's list and bingo, they start working, but...
    - user is puzzled about the SDK doc wording of the above mentioned InsertX methods, in this context.
    ...in my case, I assumed that the LayerObject(s) ownership would be taken over by the scene's list, so I didn't free them, but the docs are unclear/misleading or just plain wrong on the subject.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 18/04/2008 at 07:19, xxxxxxxx wrote:

    Quote: _ GeListHead::InsertFirst()_
    >
    > * * *
    >
    > GeListHead::InsertLast()
    > GeListNode::InsertBefore()
    > GeListNode::InsertAfter()
    > GeListNode::InsertUnder()
    > GeListNode::InsertUnderLast()

    >
    > ...In each of the above, the docs say "...The caller owns the pointed object" (the one being passed in / inserted).
    >
    > Since the pointer had to come from 'somewhere' (the user/code will already know where), the sentance must be addressing the issue of "who needs to free the object"... and in that context (after an insertion/addition to some C4D maintained scene/document/list), it would only make sense if C4D was cloning the objects. If it's not, then the docs are - explicitly - wrong and need updating.
    >
    >
    >
    > * * *

    Nope it´s not wrong, it´s right. :) For all these commands, when you insert into an existing list, the list will take over the ownership. There is no need for the scene (or list) to clone the object. Why should it? It only states that when passing the object you must own it so it can asure that there is no trouble when taking over the ownership.

    I agree though that an addition that explicitly says "the list you insert bn to takes over the ownership" would be useful (they already state the Remove() function which could then give you the answer, but well, not very convenient).

    GeListHead is a special case. It´s nothing you could use for scene management and most probably these lists do not belong to user interaction (at least in 6 years, I never dealt with GeListHead in any way...there´s only a handful of functions in the SDK using this class), so you can easily disregard it.

    Edit: Haha, in this very second I just kept on reading the example. :) Well, in that case there is obviously a GeListHead. Also here I would simply suggest an additional statement. Is the layerobject in your ownership?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 18/04/2008 at 07:29, xxxxxxxx wrote:

    Ah, ok, just looked into the docs and for this GetLayerthingy scenario you are right I must confess. It really is misleading that there is no info. One indeed assumes, at least for GeListHead, that using InsertXX functions would let the list take over the ownership.

    Scandal! :) Seriously, I see the point in it. thx for pointing out this!



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 18/04/2008 at 08:35, xxxxxxxx wrote:

    I agree with Samir's assessment completely. Anytime that you are inserting something into C4D's lists, C4D takes over ownership. Almost every instance that C4D passes to you remains in its ownership unless the passing is through a method removing it from a list.

    I've never really dealt with GeListHead either - rarely directly work with GeListNode (except in the capacity that it is a base class for many others).

    To wax on here, this ownership thing for freeing resources is a big enigma with languages like C/C++. Many developers aren't taught about it in any depth unless they've been schooled or do a lot of research. With Java (and COFFEE), ownership is never an issue since instances are freed by a garbage collection system when they go out of scope. Imho, not only tracking memory allocations but also ownership is the minutia that made me go from C to Java in the first place. I only use C++ for doing C4D plugins. :)


Log in to reply