Problem with C# not calling MC++ destrcutor

J

Jeremy Chaney

I have an application written in C# that uses objects written in a
managed C++ DLL. When I exit my app, my C# classes have their
destructors called, but the MC++ objects that those classes hold
references to do not get invoked (I can observe this from both
breakpoints in the code, and trace output to the console).

I was under the impression that when my C# object goes out of scope, it
would automatically dispose of all of the references it is holding. I'm
new to GC, so maybe it doesn't work this way? I know that during
application execution objects with a ref count of 0 might not be cleaned
up right away, but when my process exits, shouldn't I be able to rely on
all of my objects being garbage collected?

Thanks,
--Jeremy
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jeremy said:
I have an application written in C# that uses objects written in a
managed C++ DLL. When I exit my app, my C# classes have their
destructors called, but the MC++ objects that those classes hold
references to do not get invoked (I can observe this from both
breakpoints in the code, and trace output to the console).

I was under the impression that when my C# object goes out of scope, it
would automatically dispose of all of the references it is holding. I'm
new to GC, so maybe it doesn't work this way? I know that during
application execution objects with a ref count of 0 might not be cleaned
up right away, but when my process exits, shouldn't I be able to rely on
all of my objects being garbage collected?

Thanks,
--Jeremy

Managed classes doesn't have destructors, as there are no reference
counters at all, so nothing happens when the last reference goes away.
They may have Finalizers, that is instead called when the objects are
going to be garbage collected. You should avoid having a Finalizer on a
class if you don't need one, as having a Finalizer means that the object
has to go through at least two garbage collection cycles before it's
released.

If you need to release unmanaged resources in your classes, you should
implement the IDisposable interface (which includes have a Finalizer as
backup). If you only have managed resources in your classes, there is
nothing that you need to release, and so you don't need any Finalizer.

When the application ends, it will try to call the Finalizer of all
objects that has one, but if this takes too much time, it will just kill
the objects anyway. This is another reason to avoid having a Finalizer
if you don't need one, so that the finalizing queue only contains
objects that really needs to be finalized.
 
J

Jeremy Chaney

I guess you are technically correct about managed objects not having a
destructor, but they do support "~MyClass". In .NET-land should I be
referring to that as a Finalizer instead of a destructor?
As far as cleaning up resources, is it acceptable to put my clean up
code in "~MyClass" but also make use of manually calling
myClass.Dispose()? There are cases where I know that I don't need
certain objects anymore and it would be nice if I could put my cleanup
code in one place and know that it would be called regardless of what
caused the object to be destroyed.

I'm pretty surprised to hear that it is possible for my Finalizers to
not be called at shutdown. If I am being required to manually free up my
resources, what is the point of GC?

Thanks,
--Jeremy
 
L

Lebesgue

I'm pretty surprised to hear that it is possible for my Finalizers to
not be called at shutdown. If I am being required to manually free up my
resources, what is the point of GC?

GC is here to clean up unreferenced _memory_. You should deal with other
(unmanaged) resources using the dispose pattern in C#. There has been a long
thread recently (named C++/CLI is the way to go) where a reference counted
model for disposing unused resources in C# has been proposed.

Can you show us your finalizers? My guess is you are trying to use them the
way they were not meant to be.
 
J

Jeremy Chaney

Lebesgue said:
GC is here to clean up unreferenced _memory_. You should deal with other
(unmanaged) resources using the dispose pattern in C#. There has been a long
thread recently (named C++/CLI is the way to go) where a reference counted
model for disposing unused resources in C# has been proposed.

Can you show us your finalizers? My guess is you are trying to use them the
way they were not meant to be.

I think I'm sinking in over my head here... :) When you say Finalizers,
do you mean my "~MyClass" method?

Here it is:

~MyCSharpClass()
{
foreach (KeyValuePair<Char, MyManagedCPPClass> kvp in m_MyMap)
{
kvp.Value.Dispose();
}
m_myotherManagedCPPClass.Dispose();
}


The need for this destructor (I'm going to call it that until someone
tells me what to call it in C#) is surprising to me. The objects that I
have to call Dispose on are both Managed C++ objects. Shouldn't they
have their destructors called when "~MyCSharpClass" is called? . Before
I added the calls to Dispose, "~MyCSharpClass" was always called, but
the destructors for my Managed C++ objects were not. (I fixed this with
the addition of Dispose).

Thanks,
--Jeremy
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jeremy said:
I guess you are technically correct about managed objects not having a
destructor, but they do support "~MyClass". In .NET-land should I be
referring to that as a Finalizer instead of a destructor?

In my opinion, yes you should.

In the framework they are called finalizers, for example in the
SuppressFinalize method of the GC (garbage collector) class. They are
sometimes called destructors as they have the same syntax as C++
destructors, but I think that sticking to the name finalizers will cause
less confusion, as they work differently.
As far as cleaning up resources, is it acceptable to put my clean up
code in "~MyClass" but also make use of manually calling
myClass.Dispose()?

Actually, you should do it the other way around. In the proposed
implementation of the IDisposable interface, the finalizer is calling
Dispose(false);

The Dispose method should call the GC.SuppressFinalize method for the
object. This will remove the object from the finalizing queue,
effectively turning the object into a managed resource that safely can
be removed by the garbage collector.
There are cases where I know that I don't need
certain objects anymore and it would be nice if I could put my cleanup
code in one place and know that it would be called regardless of what
caused the object to be destroyed.

Implementing IDisposable with a finalizer as backup (which is the
proposed way to do it), will take care of that.

You should always try to call Dispose if you can, as that is a more
efficient way of freing up the resources.
I'm pretty surprised to hear that it is possible for my Finalizers to
not be called at shutdown. If I am being required to manually free up my
resources, what is the point of GC?

You should always try to free up all unmanaged resources as soon as
possible. That is usually before the application ends. Using finalizers
for freeing up unmanaged resources is just a backup. It's nice to have,
but you shouldn't rely on it completely.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jeremy said:
I think I'm sinking in over my head here... :) When you say Finalizers,
do you mean my "~MyClass" method?

Yes, he does.
Here it is:

~MyCSharpClass()
{
foreach (KeyValuePair<Char, MyManagedCPPClass> kvp in m_MyMap)
{
kvp.Value.Dispose();
}
m_myotherManagedCPPClass.Dispose();
}


The need for this destructor (I'm going to call it that until someone
tells me what to call it in C#) is surprising to me. The objects that I
have to call Dispose on are both Managed C++ objects.

As you use objects that implement IDisposable, your class should also
implement IDisposable, so that the resurces can be freed safely and as
soon as possible.

If you are using the finalizer to free the resources, you have
absolutely no control over when it happens. If you implement
IDisposable, you can call the Dispose method when you want to free the
resources.
Shouldn't they
have their destructors called when "~MyCSharpClass" is called?

No. After your finalizer has run, there will be no references to the
child objects. At the next garbage collection they will be placed in the
queue of object to be finalized, and a background process will call
their finalizers eventually.

If you implement IDisposable (with Dispose containing the code that you
currently have in the finalizer), it will make the memory management
much more efficient. After you have called Dispose, there are no
finalizers to handle, and the garbage collector can free the memory of
your object and all it's child objects at the same time.
 
L

Lebesgue

The need for this destructor (I'm going to call it that until someone
tells me what to call it in C#) is surprising to me.
Actually, there's no need for it in the form you have posted. See below how
to implement it "correctly".
Shouldn't they have their destructors called when "~MyCSharpClass" is
called?
No, finalizers (or call them destructors) don't call finalizers on instance
members automatically (I don't know if and under which circumstances they do
in C++, but I guess you think they do in C#). As Göran has stated in the
reply below, objects that have finalizers are placed in the finalization
queue and GC calls their finalizers on its finalizing thread when it finds
appropriate.

While Göran has explained the "theory" of what you should do, please let me
sum up how to implement what you have in practice.
Your finalizer code (the code you've posted) should go to the Dispose(bool
disposing) method you'll add to your class. You will also implement
IDisposable interface and from its Dispose() method, you'll call
Dispose(true) and also call GC.SuppressFinalize(this); - which will prevent
the object to be placed in the finalization queue => the finalizer will not
be called when the object is collected. Your finalizer would call the
Dispose(bool) method and you have done so already, that's why you are
calling SuppressFinalize().

Your finalizer should call Dispose(false) which will get rid of all
references to its instance members (set them to null) and rely on let their
finalizers to be called in the next collection (in case they have any and
they have not been Disposed yet). You should not rely on the finalizer to be
called - it's there just for the case you "forget" to call
IDisposable.Dispose() method on your object.

The whole point you are missing, I think, is that IDisposable.Dispose() is
meant to be called deterministically by you when you know you need to clean
up the resources used by the object.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top