Memory management in GVO

On 22/03/2013 at 10:05, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R13 
Platform:   Windows  ;   
Language(s) :     C++  ;


I've written a kind of cloner object using GetVirtualObjects. I alloc instances of the original object and group it under a null. I'm now wondering if this will produce a memory leak, since the objects will never be freed, f.ex. if the user switches off the generator.

Additional, I would kindly ask you, if you think, this is the best method due to performance. It may produce thousends of clones.

BaseObject *IMVertec::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)   
     BaseDocument     *doc = hh->GetDocument();   
     BaseContainer     *bc = op->GetDataInstance();     // Daten-Container   
     BaseObject          *tp = op->GetDown();               // Tracker-Masterobjekt   
     if (!tp || !bc->GetBool(INIT))   
          op->SetDeformMode(FALSE);                    // Objekt ausschalten   
          bc->SetBool(INIT, FALSE);   
          return NULL;   
     Bool dirty = FALSE;   
     BaseObject *pp = op->GetAndCheckHierarchyClone(hh, tp, HIERARCHYCLONEFLAGS_ASIS, &dirty;, NULL, TRUE);   
     if (!dirty) return pp;   
     if (!pp) return NULL;   
     // Tracker-Klone erzeugen und auf dem Grid positionieren   
     AutoAlloc<BaseLink> link;   
     BaseObject               *gp = bc->GetObjectLink(IMV_GRID_LINK, doc);   
     Matrix                    mg = gp->GetMg();   
     BaseObject               *mp = BaseObject::Alloc(Onull);   
     if (!mp || !link) goto Error;   
     LONG               i, pcnt = ToPoly(gp)->GetPointCount();   
     const Vector     *pAdr = ToPoly(gp)->GetPointR();   
     for (i=0; i<pcnt; i++)   
          BaseObject *cp = BaseObject::Alloc(Oinstance);   
          if (!cp) goto Error;   
          cp->SetParameter(DescLevel(INSTANCEOBJECT_LINK), GeData(link), DESCFLAGS_SET_0);   
          cp->SetRelPos(pAdr[i] * mg);   
     return mp;   
     return NULL;   

Maybe, the source code of the C4D cloner object is available somewhere?

Thanks for your assistance.

On 22/03/2013 at 11:51, xxxxxxxx wrote:

The objects will be freed by Cinema. By returning them from GVO, the ownership goes to the Application.
This is stated in the docs, when I remember correctly.


On 22/03/2013 at 13:27, xxxxxxxx wrote:

blDelete(mp), I think this is incorrect. You should use BaseObject::Free().

On 23/03/2013 at 08:36, xxxxxxxx wrote:

Thanks. I copied that from the atom example of the sdk. But I remeber also that it's better to use Free.

On 23/03/2013 at 08:38, xxxxxxxx wrote:

The SDK says:

static void blDelete(BaseList2D*& bl)

Destructs objects derived from BaseList2D. It's basically the same as BaseList2D::Free().

On 23/03/2013 at 08:56, xxxxxxxx wrote:

Hi Klaus,

Destructs objects derived from BaseList2D. It's basically the same as BaseList2D::Free().

Ok, I confused it with bDelete().


On 24/03/2013 at 03:43, xxxxxxxx wrote:

Using  blDelete() or BaseList2D::Free() is really dangerous in bigger projects.
Using smart pointers like  AutoFree<BaseList2D>  is more safe way to to this.
BaseObject *IMVertec::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
    	 BaseDocument      *doc = hh->GetDocument(); 
    	 BaseContainer     *bc = op->GetDataInstance();     // Daten-Container
    	 BaseObject        *tp = op->GetDown();               // Tracker-Masterobjekt
    	 if (!tp || !bc->GetBool(INIT)) {
    		  op->SetDeformMode(FALSE);                    // Objekt ausschalten
    		  bc->SetBool(INIT, FALSE);
    		  return NULL;
    	 Bool dirty = FALSE;
    	 //BaseObject *pp = op->GetAndCheckHierarchyClone(hh, tp, HIERARCHYCLONEFLAGS_ASIS, &dirty, NULL, TRUE); 
    	 AutoFree<BaseObject> pp( op->GetAndCheckHierarchyClone(hh, tp, HIERARCHYCLONEFLAGS_ASIS, &dirty, NULL, TRUE) );
    	 if (!dirty) return pp.Release(); //if you forget Release() here then C4D will crash 
    	 if (!pp) return NULL;
    	 // Tracker-Klone erzeugen und auf dem Grid positionieren
    	 AutoAlloc<BaseLink> link;
    	 BaseObject               *gp = bc->GetObjectLink(IMV_GRID_LINK, doc);
    	 Matrix                    mg = gp->GetMg();
    	 AutoFree<BaseObject>      mp( BaseObject::Alloc(Onull) ); //can also be replaced with AutoAlloc<BaseObject>
    	 if (!mp || !link) goto Error;
    	 LONG          i, pcnt  = ToPoly(gp)->GetPointCount();
    	 const Vector  *pAdr = ToPoly(gp)->GetPointR();
    	 for (i=0; i<pcnt; i++)
    		//this is only one place where AutoFree is not really necessary for now, 
    		//but if this for loop will grow over times then it will be.
    		  AutoFree<BaseObject> cp( BaseObject::Alloc(Oinstance) ); 
    		  if (!cp) goto Error;
    		  cp->SetParameter(DescLevel(INSTANCEOBJECT_LINK), GeData(link), DESCFLAGS_SET_0); 
    		  cp->SetRelPos(pAdr[i] * mg);
    		  cp.Release(); // this is important because cp now belong to mp.
    	 //if you forget Release() here then C4D will crash and you will know why, but no memory leaks will happens.
    	 return mp.Release(); 
    Error: //this is not really needed any more.
    	//pp.Free(); //blDelete(pp);
    	//mp.Free(); //blDelete(mp);
    	return NULL;

On 25/03/2013 at 03:25, xxxxxxxx wrote:

Thanks Remo, I will try it.

On 25/03/2013 at 03:52, xxxxxxxx wrote:

C4D crashes immidiately. Switching back to the old call of GVO works. This looks coherent for me, since there is no allocation of the virtual object pp at all.

On 25/03/2013 at 04:34, xxxxxxxx wrote:

of course it will crash :)

    if (!dirty) return pp.Release(); //if you forget Release() here then C4D will crash

Crash is better as memory leak, it is much easier to find and to fix.


On 29/03/2013 at 05:17, xxxxxxxx wrote:

Rendering doesn't work. Dirty is always FALSE. Any ideas?