Memory management in GVO



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

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

    ---------
    Hi,

    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;   
      
         link->SetLink(tp);   
      
         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);   
              cp->InsertUnderLast(mp);   
         }   
         return mp;   
    Error:   
         blDelete(pp);   
         blDelete(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.

    Best,
    Niklas



  • 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().

    Best,
    -Niklas



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

    Hi,
     
    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;
         
        	 link->SetLink(tp);
        	 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->InsertUnderLast(mp);
        		  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;
        }
        
    
    Remo
    


  • 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.

    Remo



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

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


Log in to reply