destroyng object

J

josh

Hi,

I have an important doubt!

If in my class I implement a Dispose() method and then call it from
my application is it useful only for free unmanaged resources?

the object itself is then discarded from heap memory by the GC when it
wants?

my doubt is, for example, if MyObj has a destructor:

{
MyObj o = new MyObj();

....

o = null;

}

then here when o is out of scope the GC call the destructor, if
present, but the object itself is then
destroyed from memory when it wants?

Thanks
 
M

Marc Gravell

If in my class I implement a Dispose() method and then call it from
my application is it useful only for free unmanaged resources?

Dispose is used (in preference to a finalizer) to allow deterministic
clean-up; this isn't necessarily anything to do with unmanaged resources
- for instance, it could be putting a managed object back into a pool,
releasing a lock at a known time, performing a transaction rollback - etc.

Dispose does not directly affect GC, and the /collection/ of a disposed
object is still non-deterministic; however, if the Dispose() method
releases other managed objects (i.e. sets some fields to null), then
those other objects might become eligible for collection, even if the
parent object is still in scope.

Finalize *is* generally used with managed resources, but often as a
safety net around IDisposable - i.e. so that a file handle gets closed
(eventually) in either case.

Marc
 
J

josh

Finalize *is* generally used with managed resources, but often as a
safety net around IDisposable - i.e. so that a file handle gets closed
(eventually) in either case.

Ok but I don't understand the following:

when a reference object is assigned a null value this meaning that the
object
pointed become eligible for collection. When than that reference is
out of scope
and I put a destructor method then the GC call it and execute the code
in it but
I wonder the object itself is after the execution of the destrucor
method discarded from the heap?
 
A

Anthony Jones

josh said:
Hi,

I have an important doubt!

If in my class I implement a Dispose() method and then call it from
my application is it useful only for free unmanaged resources?

the object itself is then discarded from heap memory by the GC when it
wants?

my doubt is, for example, if MyObj has a destructor:

{
MyObj o = new MyObj();

...

o = null;

}

then here when o is out of scope the GC call the destructor, if
present, but the object itself is then
destroyed from memory when it wants?


Dispose is really only necessary where unmanaged resources are concerned
(which may be indicated simply because an internally holds objects that have
a Dispose).

Assuming you have called Dispose in the code above the assigment of null
into o is superflous.

It may be that you have a purely managed object that allocates a large
amount of memory. For example:-

{

MyObj o = new MyObj() // allocates a lot of memory

// code that uses o

// long running code in scope with o but not using o

}

In the above case the memory used by o will remain uncollected by the GC
since it will still be 'in-use' for its perspective. Inserting an o = null;
would suffice in allowing the GC to recover the memory if it sees the need.

BTW, assigning something to null does not invoke the finalisation of the
object or cause the GC to do any work. The GC does that according to its
own schedule and algorithms.

I would be inclined to implement IDispose in this case. The Dispose method
would assign null to internal variables holding reference to the memory
guzzling items. Since this memory won't be recovered until the GC chooses
to collect it the implementation of IDispose isn't really necessary.
However the presence of IDispose communicates to the developer the need to
dispose of the object with greater prejudice than other types.
 
M

Marc Gravell

If I understand that last line correctly: if an object has a finalizer
(and that finalizer hasn't been suppressed), then the finalizer is
invoked on the first pass through GC. The memory is released on a second
pass through GC.

For objects without a finalizer (or where the finalizer *is*
suppressed), the memory is released on the first pass.

Marc
 
A

Anthony Jones

josh said:
Ok but I don't understand the following:

when a reference object is assigned a null value this meaning that the
object
pointed become eligible for collection. When than that reference is
out of scope

Variables go out of scope not references.

As soon as you've assigned null to a variable there is no longer any
connection between the current scope of execution and the object. If there
are no other variables pointing to that object the GC could interrupt code
running in your scope and clean up the object.
and I put a destructor method then the GC call it and execute the code
in it but
I wonder the object itself is after the execution of the destrucor
method discarded from the heap?

The memory occupied by the object is released as available memory for
allocation by the GC immediately after the GC has finalised the object.
 
M

Marc Gravell

Dispose is really only necessary where unmanaged resources are concerned

I'm sorry, but I would disagree; this is generally true of finalize, but
Dispose() is sometimes used in some scenarios that have nothing to do
with unmanaged resources.
Assuming you have called Dispose in the code above the assigment of null
into o is superflous.

Setting to null and Dispose() have nothing at all to do with each-other.
 
A

Anthony Jones

Marc Gravell said:
I'm sorry, but I would disagree; this is generally true of finalize, but
Dispose() is sometimes used in some scenarios that have nothing to do
with unmanaged resources.

I defer to you expertise, you identified those in your other post.
However, I did go on to describe a managed scenario myself afterward
although not as well as you did.
Setting to null and Dispose() have nothing at all to do with each-other.

Indeed. That is absolutely technically correct. In real world common sense
terms I believe my statement to be correct and there is no conflict between
what you have stated and my comment.

Perhaps I'm showing my ignorance here. Can you give me an example of an
object that is disposable and yet the act of assigning a variable
referencing it to null is also significant?
 
J

josh

Variables go out of scope not references.

if I have the following block:

{
int a = 10;

Obj o = new Obj();
}

a = 11; // error type var out of scope
o = new Obj(); / /errorr reference var out of scope

the compiler give:

Error The name 'a' does not exist in the current context

Error The name 'o' does not exist in the current context
 
D

d-42

if I have the following block:

{
int a = 10;

Obj o = new Obj();

}

a = 11; // error type var out of scope
o = new Obj(); / /errorr reference var out of scope

the compiler give:

Error The name 'a' does not exist in the current context
Error The name 'o' does not exist in the current context

Those are *both* variables.

If you have the following code

{
Object myobject = new Object();
myfunc()
myobject.DoSomething(); // myobject didn't get eaten!!
}

myfunc()
{
myobject = new Object(); // error myobject does not exist in the
current scope
// myobject is out of scope, will the GC eat it?! Of course not.
}

The point is even while running myfunc(), myobject is still has a
valid reference to it, and I don't have to worry about it being eaten
by the garbage collector while myfunc is running. That's all the GP
poster was referring too. I think.

-cheers,
Dave
 
M

Marc Gravell

Can you give me an example of an
object that is disposable and yet the act of assigning a variable
referencing it to null is also significant?

It depends on what Dispose() [if called] and/or the finalizer (if one)
do ;-p
There are some tortured cases involving dodgy Dispose() implementations
(the WCF client-proxy, for example, regularly throws an exception on
Dispose(), which is annoying) - but personally (and for sanity) I try to
keep it simple:

* If an instance is IDisposable, and I "own" it, then Dispose() it,
ideally via "using".
* Properly release any high-cost fields (instance variables) when they
are no longer needed - perhaps in a Dispose() implementation.

I don't normally recommend confusing the code of methods by adding lots
of "o = null" stataments; in 99% of cases they are unnecessary (or even
detrimental), and in the remaining 1% you need a much deeper
understanding of the memory model anyway... and in 100% of those cases
it makes the code harder to read, which is never a good thing.

Marc
 
A

Anthony Jones

josh said:
if I have the following block:

{
int a = 10;

Obj o = new Obj();
}

a = 11; // error type var out of scope
o = new Obj(); / /errorr reference var out of scope

the compiler give:

Error The name 'a' does not exist in the current context

Error The name 'o' does not exist in the current context

Yep that's right, the identifiers a and o are not in context. Were you
asking for further clarification or simply making a confirmation?
 
J

josh

Yep that's right,  the identifiers a and o are not in context.  Were you
asking for further clarification or simply making a confirmation?

oh simply a confirmation!
 
M

Marc Gravell

 I think it's very important to make sure everyone understands why  
he wrote that.

That is what I had in mind - but I didn't have my CLR spec "to hand",
so I couldn't remember for sure if this was fact or legend ;-p

Marc
 
D

d-42

[...]
myfunc()
{
myobject = new Object(); // error myobject does not exist in the
current scope
// myobject is out of scope, will the GC eat it?! Of course not.
}

CAREFUL!

The code above doesn't compile, since "myobject" isn't declared. So it's
difficult to tell for sure what you meant to demonstrate. For sure,
having the only reference to an object being out of scope is sufficient
for an object to be collected.

That was precisely was I trying to illustrate. That having the only
reference to an object being out of scope is -not- sufficient for an
object to be collected, assuming we mean the same thing by scope at
least.

To revise my example slightly:

{
Object myobject = new Object();
myfunc()
myobject.DoSomething(); // myobject didn't get eaten!!

}

myfunc()
{
// the name myobject is out of scope right now, and it is the
// only reference to the object
// but there is no chance it will be GC'd
// because when myfunc returns
// the myobject comes back into scope,
// **and** it is accessed (which addresses the second part of
your post)
}

[...]
But your statement is incorrect. You _do_ have to worry "about it being
eaten by the garbage collector while myfunc is running". If the code
never uses that variable again, the reference is eligible for collection
even while the function is still executing.

Fair enough.

I was only trying illustrate how it would be possible for all the
references to an object to be [temporarily] out of scope and yet the
object would not be eligible for garbage collection.

I guess it would be more accurate to say that its possible for all the
references to an object to be out of scope and yet the object is not -
necessarily- eligible for garbage collection.

-regards,
Dave
 
B

Barry Kelly

d-42 said:
That was precisely was I trying to illustrate. That having the only
reference to an object being out of scope is -not- sufficient for an
object to be collected, assuming we mean the same thing by scope at
least.

Scope is a compile-time concept, and refers to names (including variable
names).

Reachability (which is what the GC uses) is a run-time concept, and
refers to values (including stack and heap values).

There's no trivial mapping between the two. Talking about 'scope' when
discussing GC can be misleading, because the GC does not use scope to
determine reachability.
To revise my example slightly:

{
Object myobject = new Object();
myfunc()
myobject.DoSomething(); // myobject didn't get eaten!!

Not necessarily. See below.
}

myfunc()
{
[..]
}

Actually, if myobject.DoSomething() doesn't access the 'this' implicit
parameter in its body or any of the methods that it calls, myobject can
*still* be collected, even while the instance method DoSomething() is
being called.

Both virtual and non-virtual calls count as accesses of the 'this'
implicit parameter, as C# uses 'callvirt' for both. However, in other
languages, 'call' may be used for instance methods; in this case, the
object may still be freed before the instance method is called, such as
during the 'myfunc()' invocation.
I was only trying illustrate how it would be possible for all the
references to an object to be [temporarily] out of scope

Please, be careful with the word 'scope'. It is a compile-time concept.
Most of the time, almost all variables in the program are not 'in
scope', unless you make most of your variables static and write most of
your methods as static methods in the same class as the variables.

-- Barry
 
A

Anthony Jones

Peter Duniho said:
As I noted in my other replies in this thread, that's not true. If the
rest of the code "in scope" does not use "o", then the GC can collect the
instance. The variable being in scope doesn't matter, and setting the
variable to null can only delay the collection of the object (it creates
one more use of the variable, beyond the actual last point where it really
needs to be used, which moves the point in the method at which the GC
could collect the instance farther down than it would be otherwise).

Marc hints at this when he writes "in 99% of cases they are unnecessary
(or even detrimental)", in reference to setting variable in methods to
null. I think it's very important to make sure everyone understands why
he wrote that.


Thanks Pete, I hadn't grasped that, I get it now.
 

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