jxbma
asked on
Why does the destructor for my CLI/CPP ref class not get called (which results in a memory leak)?
Hi:
I have some questions regarding use of gcnew and explicitly calling delete on the created object.
It appears that I have a leak in my code.
Consider the following example.
I have an unmanaged class:
I have a managed class which wraps the unmanaged class:
I have a method which returns a handle to the managed class to a .Net C# client:
It's my understanding that since Foo is created on the managed heap that I do not have to explicitly
delete it. Garbage Collection (GC) on the managed side should take care of it.
The problem in my case is that the destructor of my managed class never seems to get called.
The results in the interior pointer to my unmanaged class getting (memory) leaked.
What is the correct way to handle this situation so that the underlying unmanaged class (FooBar) gets
correctly freed (when the managed wrapper class goes out of scope)?
Thanks,
JohnB
I have some questions regarding use of gcnew and explicitly calling delete on the created object.
It appears that I have a leak in my code.
Consider the following example.
I have an unmanaged class:
public class FooBar
{
int x;
int y;
}
I have a managed class which wraps the unmanaged class:
ref class Foo
{
private FooBar* pFooBar;
Foo()
{
pFooBar = new FooBar();
}
Foo()
{
delete pFooBar;
pFooBar = nullptr;
}
}
I have a method which returns a handle to the managed class to a .Net C# client:
public Foo^ GetMeAFoo()
{
Foo^ foo = gcnew Foo();
return foo;
}
It's my understanding that since Foo is created on the managed heap that I do not have to explicitly
delete it. Garbage Collection (GC) on the managed side should take care of it.
The problem in my case is that the destructor of my managed class never seems to get called.
The results in the interior pointer to my unmanaged class getting (memory) leaked.
What is the correct way to handle this situation so that the underlying unmanaged class (FooBar) gets
correctly freed (when the managed wrapper class goes out of scope)?
Thanks,
JohnB
You're not deriving from IDisposable on the .NET side. That seems to be the problem to me...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>>when the managed wrapper class goes out of scope)?
The problem is probably a lack of understanding. The garbage collector will call a destructor when the class is removed from memory. However the GC mechanism does not remove a class from memory when it goes out of scope - it removes it from memory when the memory is required again or when the app is closed. This is not what one expects compared to unmanaged code - you do not have a memory leak.
The problem is probably a lack of understanding. The garbage collector will call a destructor when the class is removed from memory. However the GC mechanism does not remove a class from memory when it goes out of scope - it removes it from memory when the memory is required again or when the app is closed. This is not what one expects compared to unmanaged code - you do not have a memory leak.
you may consider to putting the creation of unmanaged objects into unmanaged code. the managed class then would only hold a 'handle' of the unmanaged object.
the managed class would create FooBar via handler.
and delete it after use.
Sara
typedef FooBar * FBHDL;
class UnmanagedFooBarHandler
{
std::vector<FooBar*> allbars;
// private constructor makes it a singleton
UnmanagedFooBarHandler() {}
~UnmanagedFooBarHandler() { while (allbars.size()) { delete allbars[0]; allbars.erase(allbars.begin()); }}
public:
static UnmanagedFooBarHandler & UFBH()
{ static UnmanagedFooBarHandler ufbh; return ufbh; }
FBHDL createFooBar() { allbars.push_back(new FooBar()); return (FBHDL)allbars.back(); }
void deleteFooBar(FBHDL fb)
{ std::vector<FooBar*>::iterator f = std::find(allbars.begin(), allbars.end(), fb);
if (f != allbars.end()) { delete *f; allbars.erase(f); }
}
...
};
the managed class would create FooBar via handler.
FBHDL fb = UFBH().createFooBar();
and delete it after use.
UFBH().deleteFooBar(fb);
Sara
ASKER
I added a finalize to the classes in question and all is well.