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?