Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Memory management in GVO

    SDK Help
    0
    11
    821
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      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.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        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

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

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

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

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            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.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

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

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                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

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  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
                  
                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

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

                    Thanks Remo, I will try it.

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      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.

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        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

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

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

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

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post