Destructon of .NET objects

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

Why doesnt the runtime set the object to null when the finalizer has been
called? Wouldnt this prevent a slew of bugs?

I just called the obj.__dtor(); from a MC++ wrapper class I made and its
still referencing the type even tho its "destructed". Why do I have to set
it to null in my view it should be set by destruction.

????
 
Why doesnt the runtime set the object to null when the finalizer has been
called? Wouldnt this prevent a slew of bugs?

Where exactly would it set it to null? Would you want it to walk
through the entire managed heap (and stack) to find all references to
the object? If there are references to the object, why has it been
finalized in the first place? Presumably either because the objects
referring to it are eligible for garbage collection too, or because it
doesn't know the type of the data, in which case it wouldn't know to
set that to null anyway.

Note that there's no such thing as "setting an object to null" -
there's only setting the value of a reference-type variable to null.
 
Jon Skeet said:
Where exactly would it set it to null? Would you want it to walk
through the entire managed heap (and stack) to find all references to
the object? If there are references to the object, why has it been
finalized in the first place? Presumably either because the objects
referring to it are eligible for garbage collection too, or because it
doesn't know the type of the data, in which case it wouldn't know to
set that to null anyway.

If it doesnt know where to set it to null, then how does it know what and
where the object reference is in the first palce.
Ofcourse it can set the reference to null, its knows where it is, what it is
and its been destructed, simple matter of setting that reference to null.
Note that there's no such thing as "setting an object to null" -
there's only setting the value of a reference-type variable to null.

Thats what I mean.
 
If it doesnt know where to set it to null, then how does it know what and
where the object reference is in the first palce.
Ofcourse it can set the reference to null, its knows where it is, what it is
and its been destructed, simple matter of setting that reference to null.

As Jon said, why is it being finalized when you still have a reference to
it? It wouldn't be garbage collected if it was 'live'.

It knows where the object is, but not its references. IIRC the garbage
collector works by determining which objects are live, and then removing the
others (as, by definition, they are not live) so it wouldn't know *where*
they were being referenced unless it touched *everything* :) I think this is
what Jon was implying?

n!
 
If it doesnt know where to set it to null, then how does it know what and
where the object reference is in the first palce.

Usually it does - but you may have some opaque data which the GC
doesn't know about. Don't forget that the GC won't have necessarily
walked all paths where there might be a reference - only paths where
there might be a reference which would keep the object alive.
Ofcourse it can set the reference to null, its knows where it is, what it is
and its been destructed, simple matter of setting that reference to null.

But if there are non-null references, why is the object being destroyed
in the first place? It has to be due to all the other references being
within objects which are about to be destroyed anyway - so why do you
care? (Note that the object itself won't be destroyed until everything
that has a reference to it is about to be destroyed - if there's a
finalizer which can access the object, the object can itself be
finalized but not destroyed.)
Thats what I mean.

Personally I'm happier with it not having to look all over the heap for
things to do when there's no need to.

Why do you think you need it to do this? What's your use case?
 
n! said:
It knows where the object is, but not its references. IIRC the garbage
collector works by determining which objects are live, and then removing the
others (as, by definition, they are not live) so it wouldn't know *where*
they were being referenced unless it touched *everything* :) I think this is
what Jon was implying?

Yup - although assuming it's doing its job, it would actually only need
to look at all the other objects which are eligible for garbage
collection. That's still a significant overhead, IMO.
 
Becuase I called the __dtor and that calls delete obj; in my mixed mode C++
assembly.

Just curious why it cant be set to null as this is something I would do
myself on all destructed objects. When its destructed it wont be used again
until a new reference is constructed. Setting it to null would make it
more obvious that its no longer valid and could go and construct a new
reference is thats needed.
 
If you set an object to Nothing (not null), it will cause that object's
Dispose method to fire and "flag" the object as eligible for removal from
the heap the next time the GC does its clean up. Setting the object to
Nothing won't cause its finalize method to run or remove it from the heap.

Since an object will fire its dispose method and get "flagged" as eligible
fro removal from the heap when it falls out of scope anyway, there is not
usually a need to explicitly set your objects to Nothing. You are, however,
allowed to do this as setting the object to Nothing yourself, rather than
waiting for it to fall out of scope, can speed up the call to the object's
dispose method. If you have your own code in that method, it will run a bit
sooner this way. For most applications though, the delay in waiting for the
object to fall out of scope is negligible.
 
Becuase I called the __dtor and that calls delete obj; in my mixed mode C++
assembly.

Hmm... I'm not entirely sure that calling the destructor actually
*does* delete the object. It might call the finalizer, but that's not
the same as deleting or destroying the object. I don't know much about
mixed mode C++, but I'd expect the actual memory to still be allocated
until the GC collects the object in the normal way.
Just curious why it cant be set to null as this is something I would do
myself on all destructed objects. When its destructed it wont be used again
until a new reference is constructed. Setting it to null would make it
more obvious that its no longer valid and could go and construct a new
reference is thats needed.

Keeping live references to destroyed objects strikes me as a pretty
rare (and dangerous) thing to do. Why should everyone else who relies
on the GC to do things automatically suffer nasty performance penalties
because you don't want to rely on it?
 
Well it should because its wrapping an unmanaged class, its calling the
delete.

I dare say it's deleting the unmanaged class it's wrapping, but whether
that means it's deleting the managed class itself is a different
matter.
 
Its unmanaged, so the GC wont touch it, its stored on an unmanaged heap. On
mixed mode modules you have 2 heaps, managed and unmanaged. Its you to you
to manage the unmanaged heap as you normally would. If its not deleted then
somethings seriously wrong I would imagine. As for the managed wrapper, we
cannot tell when thats destructed, are you saying that the managed type even
tho the destructor is called, its never finalized until I set it to null
myself? If it is destructed at somepoint, why cant it just set it to null
as its obviously an invalid reference at that point.
 
Its unmanaged, so the GC wont touch it, its stored on an unmanaged heap. On
mixed mode modules you have 2 heaps, managed and unmanaged. Its you to you
to manage the unmanaged heap as you normally would. If its not deleted then
somethings seriously wrong I would imagine. As for the managed wrapper, we
cannot tell when thats destructed, are you saying that the managed type even
tho the destructor is called, its never finalized until I set it to null
myself? If it is destructed at somepoint, why cant it just set it to null
as its obviously an invalid reference at that point.

I'm not *entirely* sure whether or not there's any difference between
the finalizer and the destructor - there certainly isn't in C#.

However, in the normal managed world, no - the object won't be
finalized or garbage collected until there are no live references to it
left. You can't manually force a specific object to be garbage
collected.
 
so, the reference to the object is a reference variable within your wrapper
class... right?

I assume that this is a managed code wrapper class. (not sure how you'd
have a reference to a managed code object in unmanaged code, but I'm not a
C++ developer... if you have done this: you'd have no right to complain...
the garbage collector runs in managed code... it couldn't reach in to your
unmanaged class and modify your reference variable, even if it wanted to).

Assuming all managed code: If you have a reference to the object, it has not
been garbage collected (by definition... you have a reference to it). You
may have called the destructor, which ran a method on the object, but you
are responsible for changing the value of your reference variable to 'null',
not the destructor or any part of the system.

I guess I'm as perplexed by your question as the other folks here...

--- Nick
 
Back
Top