|
Go
![]() |
New
![]() |
Find
![]() |
Notify
![]() |
Tools
![]() |
Reply
![]() |
|
|
Member |
I seem to have a situation where over time my application leaks memory. I load up a geometry and texture and associate them with a newly created instance, which is then added to the scene using IMTS_Instance3d->AddChild(). At some point later I delete the instance using IMTS_Instance3d->RemoveChild() (on the parent instance). Then the whole thing is repeated a number of times, which causes the application's memory usage to continuously increase.
My fear is that when the instance is being removed, its associated resources (gemoetry and texture) are not being removed automatically. Do I manually have to remove them before deleting the instance itself? Thanks for any ideas, Loz. |
||
|
|
Member |
Thanks, I kind of thought that was what was going on.
When you say the repository still holds a reference, I get a bit confused!! According to the SDK headers (IMTS_Instance3d.h) the repository does not own the instance, material or geometry. It specifically says that these things will be removed from the repository when the last owner dies (I assume when the refcount goes to 0). So I have one of two problems. I am using I3dFileLoader->Open() to load an ASE file, and it seems that the loader is leaving references on the objects it loads (maybe). I can't check because I don't have the code for that method. Either that, or I am using the CXPRefPtr<> template in a way that is leaking a reference. Here's a skeleton of my code: CXPRefPtr CXPRefPtr CXPRefPtr CXPRefPtr if (SUCCEEDED(CXPCreateInstance(ipMTSServices, Class3dFileLoader ::ID(), ipMTSLoader3d.Ref()))) { ipMTSInst3dA = ipMTSScene->GetRootInstance(); ipMTSInst3dB = ipMTSInst3dA->GetChild(0); ipMTSInst3dB->RemoveChild(ipMTSInst3dB->GetChildCount() - 1); if (ipMTSLoader3d->Open(ipMTSScene, cxpFileSpec)) { ipMTSInst3dB = ipMTSInst3dA->GetChild(1); ipMTSInst3dC = ipMTSInst3dA->GetChild(0); ipMTSInst3dA->RemoveChild(ipMTSInst3dB); ipMTSInst3dC->AddChild(ipMTSInst3dB, ipMTSRepository); } } It takes a scene graph like: Root Container Instance1 Instance2 InstanceX It deletes the last instance in the container (InstanceX) and loads a new ASE which gives: Root Container Instance1 Instance2 InstanceNew and then moves the new instance (just loaded) into the end of the container: Root Container Instance1 Instance2 InstanceNew I have noticed that IMTS_Repository->GetInstanceCount(), GetGeometryCount() and GetMaterialCount() increase each time this code has been called. So it does look like I'm/the loader are leaking an instance reference somewhere. Any further help or ideas would be appreciated. TIA, Loz. |
|||
|
|
Member |
Oops... the angle brackets were removed and other spaces stripped. Here's the CXPRefPtr declarations again with square brackets:
CXPRefPtr[IMTS_Instance3d] ipMTSInstA; CXPRefPtr[IMTS_Instance3d] ipMTSInstB; CXPRefPtr[IMTS_Instance3d] ipMTSInstC; CXPRefPtr[I3dFileLoader] ipMTSLoader3d; and here's the scene structures: Root ..Container ....Instance1 ....Instance2 ....InstanceX Root ..Container ....Instance1 ....Instance2 ..InstanceNew Root ..Container ....Instance1 ....Instance2 ....InstanceNew |
|||
|
| <Niko>
|
Well, that's dpend how the instance is inserted into the repository. I am not sure what the ASE loader is doing.
I would propose that you try the following: ipMTSInst3dB = ipMTSInst3dA->GetChild(1); ipMTSInst3dA->RemoveChild(ipMTSInst3dB); ipMTSInst3dB->SetBaseRepository(NULL); // then you can check the refcount, just to see // if anyone else is refcounting it. ipMTSInst3dB->AddRef(); CXPAssert(ipMTSInst3dB->Release()==1); By the way, is your instance the target of an animator ? because if it is the case, the animator is refcounting the instance. |
||
|
|
Member |
Thanks for the advice. I added the SetBaseRepository(NULL) and checked the refcount. I found that it was 1, which I assume is correct (when the smart pointer dies, it should go to 0 which should kill the instance finally). Without the SetBaseRepository() call, the refcount comes back as 2 so the instance is still in the repository, which it should not be.
Ok, so far so good. Unfortunately, the counts from the repository still don't go down, and the app's memory still keeps going up!!! The instance, geometry and material are all still in there. Why would I manually have to remove them? Would it be possible to check exactly what the I3dFileLoader code is doing? Perhaps you could email it to me and I will check? Then I could deallocate everything in the reverse order to the way it allocates it. I think it would be a great addition to the SDK example by the way :-) Thanks for any other ideas you can come up with. Loz. |
|||
|
| <Niko>
|
Hi, try the following thing:
if your instance has some children, try calling ClearHierarchy() on it. if it still does not solve the problem: try calling SetBaseRepository(NULL) on the geometry of the instance. (but i would be really surprised if this is it) about the repository count. it is normal it never decrement. elements are never removed from the array. they are jusr marked deleted. if you want to know the number of 'active' elements in the repository, call GetTotalActive(). |
||
|
|
Member |
Niko, I had the following hierarchy:
Instance1 ..Instance2 ....Geometry1 ....Material1 and the only way I could get all the objects to be removed from the repository was using code like this: pMaterial->SetBaseRepository(NULL); pGeometry->SetBaseRepository(NULL); pInstance2->SetBaseRepository(NULL); pInstance1->SetBaseRepository(NULL); pParent->RemoveChild(pInstance1); This is not what I expected. I have to traverse every instance (and children and grandchildren etc) to get to all the geometries and materials and then manually remove them from the repository. Obviously, this is a pain for more complex hierarchies. pInstance1->ClearHierarchy() *does not* do the same thing. Is this how its supposed to work? I wouldn't have thought so, based on the comments I read in the interface header files. Here's something strange that is what makes me wonder. If I use a call to: pInstance2->ClearAllMaterials() then the material is *automatically* removed from the repository when its last reference is released. That's more like the behaviour I expected. Your thoughts are greatly appreciated. TIA, Loz. |
|||
|
| <Niko>
|
Well, clearly this is not the way it is supposed to work. it is supposed to work like you thought it was... And i have to say i never had the problem you are describing. but i rarely use some scenes imported from ASE. the ASE loader my inserts 2 times in the repository every objects. i need to look in it.
|
||
|
| Powered by Eve Community |
| Please Wait. Your request is being processed... |
|

