memory leak or not?

S

Sericinus hunter

docschnipp said:
x ist just not existent anymore. it doesn't matter what it is. the memory
that x occupied has fallen back to the responsibility of the Garbage
Collection. Since your code does not access x anymore, it might it is already
gone. This is something the compiler does, it doesn't allocate a
register/memory/stack or whatever for it from this point on. But you can not
determine it. This is by design and actually very helpful, but has some
pitfalls.

I am talking about the situation when we are still in the scope of Foo.
Are we together?
 
G

Guest

Sericinus hunter said:
docschnipp wrote:
I am talking about the situation when we are still in the scope of Foo.
Are we together?

Yes, we are. Imagine that the compiler that creates the final machine code
has markers that say at "Foo() line 3" the first usage of x happens and the
last usage of x is at "Foo() line 10". Foo itself is 20 lines long.

Since the compiled code does not access "x" anymore it is possible that code
is created that releases the memory before the method Foo() is finished.

If that happens is totally in responsibility of the compiler/machine code.
And for you as programmer it doesn't matter since you don't access it anyway.

You can see this behaviour in the debugger. When you set a break point
behind the scope of "x" (but still in the scope of "Foo()") you will see that
you can not determine the value of "x" since it is inexistent/inaccessable
anymore (in case you enable optimization in debug builds).

The scope of "x" can be smaller than the scope of "Foo()".

I hope I answered the right question :)

doc
 
C

Cor Ligthert [MVP]

Willy,

In the case of the string we have two objects.

In the case that it was a reference than the object was not gargaged at all.

Only the address would be disapear together with the stack in the same way
as any value.

However you obvious did not see my :) and were the link was pointing to.

Cor
 
J

Jon Skeet [C# MVP]

Sericinus hunter said:
Jon, will you please provide a reference where I can read about
this?

Jeffrey Richter's book "Applied Microsoft .NET Framework Programming"
is excellent on this subject - and many others.
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
In the case of the string we have two objects.

No we don't, because string is a reference type.
In the case that it was a reference than the object was not gargaged at all.

Why not? Note that there's nothing to say that the GrabLongString
method maintains a reference to the string.

Note also that I was careful *not* to say that the string would be
eligible for garbage collection. I merely said that:

<quote>
The variable "x" does not prevent the long string from being garbage
collected (in release mode) before the end of the method, even though
it's still in scope.
Only the address would be disapear together with the stack in the same way
as any value.

The important thing is that "x" is not considered a root for the GC
earlier than most people expect. The string that x referred to *may* be
garbage collected (depending on whether there are other references to
it, and whether the garbage collector runs during the method etc)
before the Foo method finishes.
However you obvious did not see my :) and were the link was pointing
to.

Well I certainly did - but didn't see any relevance in my parameter
passing article.
 
B

Brian Gideon

Cor said:
Willy,

In the case of the string we have two objects.

A string variable will reference a single string object. Can you
clarify what you think the second object is?
In the case that it was a reference than the object was not gargaged at all.

Well, a string is a reference type and it is eligible for garbage
collection immediately after x.Length is called and even before
Console.WriteLine is called. Well, that's assuming that
GrabSomeLongString itself doesn't store a reference to it or that
string interning isn't in play. But, generally speaking I see nothing
wrong with Jon's example.
Only the address would be disapear together with the stack in the same way
as any value.

Actually, no. The object can be GC'd even before it's reference is
cleared from the stack! That's the whole point of the example and the
reasoning behind including the GC.KeepAlive method.
However you obvious did not see my :) and were the link was pointing to.

Yeah, I was wondering if you knew who wrote that. But, I don't see why
immutability has any impact on the example.
 
W

Willy Denoyette [MVP]

| Willy,
|
| In the case of the string we have two objects.
|

What two objects? Are you still refering to the snip Jon posted?


| In the case that it was a reference than the object was not gargaged at
all.
|
| Only the address would be disapear together with the stack in the same way
| as any value.
|
The string refered to by x will get collected when the GC comes along before
x leaves the method scope, provided x is the only root at the time the GC
runs.


| However you obvious did not see my :) and were the link was pointing to.
|

I did but I fail to see the relevance.

Willy.
 
G

Guest

docschnipp said:
Maybe someone with deeper knowledge of the implementation could elaborate
this a bit? It would be interesting to know.

doc

The only effect that setting the reference to null before allocating a
new object has, is that the reference will actually be null while the
new object is created.

There is nothing happening in the background when you set the reference
to null, it just changes the value of the reference, nothing more. So
the only case when it makes any difference is if there will be a garbage
collection while the new object is created.

If the reference is null at the time of that garbage collection, the
previous object may be collected, but if the reference is still
referencing the object, it can not be colleted at that time.

So in conclusion, if you expect that creating the new object will often
cause a garbage collection, and that it will be beneficial for the
performance if the previous object can be collected (e.g. if it occupies
a lot of memory), you should set the reference to null.

If the objects aren't that large, just don't bother to set the reference
to null. The previous object will be collected eventually, and having it
lying around until the next garbage collection will not have any
measurable effect on performance.

Actually, setting the reference to null may actually cost more than it
will ever save, as the operation is executed every time and it might
only make a difference every millionth time.

Also, adding things like that to the code only makes it harder to
understand. Even if it would benefit performance a little bit, it's not
worth it. Actually, if you ever do it, you should defenitely add a
comment explaining why you think it is good to do it in that particular
piece of code.
 
J

Jon Skeet [C# MVP]

That is exactly why I wrote it.

But you implied that string isn't a reference type. It is. You wrote:

<quote>
The string is immutable what you are showing is not a reference.
</quote>

What I was showing most certainly *is* a reference.
 
C

Cor Ligthert [MVP]

Jon,

My text was not meant as you read it.

I was implying that there was a new object instanced, and not only a new
reference to an existing object.

object A = MyJonObject;
is different from
string A = MyJonObject.ToString();

As it had been a "normal" reference type the object would in my idea not be
garbaged. (As it is not done in this case, to but the created string is
again a new object and that will be garbaged)

Marina was in my idea talking about normal non immutable reference types.
However I can of course not speak for here. Your sample is in my idea an
exception to the standard behaviour..

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
My text was not meant as you read it.

I was implying that there was a new object instanced, and not only a new
reference to an existing object.

You can't possibly know whether a new object was created or not.
object A = MyJonObject;
is different from
string A = MyJonObject.ToString();

I didn't call ToString() though - I called GrabSomeLongString(). We
don't know whether that method would create a new string or not - but
either way, the value of the variable would certainly be a reference.
As it had been a "normal" reference type the object would in my idea not be
garbaged. (As it is not done in this case, to but the created string is
again a new object and that will be garbaged)

String *is* a "normal" reference type. Its immutability has nothing to
do with ths.
Marina was in my idea talking about normal non immutable reference types.
However I can of course not speak for here. Your sample is in my idea an
exception to the standard behaviour..

Not at all. There's nothing special about string here. You could change
string to any other type in my example and the behaviour would be the
same.
 
C

Cor Ligthert [MVP]

Jon,

I think you are wrong, however it does nothing add to the question from the
OP.

In my opinion was the reply from Marina more than enough,

So I stop this discussion.

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
I think you are wrong, however it does nothing add to the question from the
OP.

I can't easily prove that strings behave differently to other objects
(we could use the .NET performance counters, but it's hard to do in
other ways), but I *can* prove that an object can be garbage collected
before a variable referencing it falls out of scope. Try the following
program, compiled with optimisation enabled and debug disabled:

using System;

class Test
{
~Test()
{
Console.WriteLine ("I'm being finalized");
}

static void Main()
{
Test x = MakeTest();

// Do some work which uses a lot of memory
long y=0;
for (int i=0; i < 1000000; i++)
{
byte[] b = new byte[10];
y += b.Length;
}
// Just keep the compiler honest...
Console.WriteLine (y);

Console.WriteLine ("The method still hasn't finished...");
}

static Test MakeTest()
{
return new Test();
}
}

On my box, the output is:
I'm being finalized
10000000
The method still hasn't finished...

Now, I suppose you *could* try to argue that even though the object is
clearly being finalized, it may not have been garbage collected - but
it seems pretty unlikely that the GC would go to the trouble of
finalizing an object if it didn't want to actually collect it.
In my opinion was the reply from Marina more than enough,

Except that it's not the whole story. It's important to understand that
things can be eligible for garbage collection before they fall out of
scope. People have been caught out before due to this, for instance
using a mutex to make sure there's only one instance of the application
running: if the mutex is finalized and then garbage collected before
they expect it to be, that can mean the program behaves unexpectedly.
So I stop this discussion.

Well, you've claimed that I'm wrong about something, and I'd appreciate
you backing that up with some evidence. I've backed up my side of
things above. It's not like this is a matter of opinion, and it *is*
important that people reading this thread can get a definitive answer -
it can easily affect whether or not they write correct code, as shown
above.
 
C

Cor Ligthert [MVP]

Jon,

I did not discuss that and don't have in any way an other opinion. Why are
you forever proving things that I don't deny.

I only say that a string is an in the method created object, while non
immutable objects are just references, if they ain't created new.

Cor

Jon Skeet said:
Cor Ligthert said:
I think you are wrong, however it does nothing add to the question from
the
OP.

I can't easily prove that strings behave differently to other objects
(we could use the .NET performance counters, but it's hard to do in
other ways), but I *can* prove that an object can be garbage collected
before a variable referencing it falls out of scope. Try the following
program, compiled with optimisation enabled and debug disabled:

using System;

class Test
{
~Test()
{
Console.WriteLine ("I'm being finalized");
}

static void Main()
{
Test x = MakeTest();

// Do some work which uses a lot of memory
long y=0;
for (int i=0; i < 1000000; i++)
{
byte[] b = new byte[10];
y += b.Length;
}
// Just keep the compiler honest...
Console.WriteLine (y);

Console.WriteLine ("The method still hasn't finished...");
}

static Test MakeTest()
{
return new Test();
}
}

On my box, the output is:
I'm being finalized
10000000
The method still hasn't finished...

Now, I suppose you *could* try to argue that even though the object is
clearly being finalized, it may not have been garbage collected - but
it seems pretty unlikely that the GC would go to the trouble of
finalizing an object if it didn't want to actually collect it.
In my opinion was the reply from Marina more than enough,

Except that it's not the whole story. It's important to understand that
things can be eligible for garbage collection before they fall out of
scope. People have been caught out before due to this, for instance
using a mutex to make sure there's only one instance of the application
running: if the mutex is finalized and then garbage collected before
they expect it to be, that can mean the program behaves unexpectedly.
So I stop this discussion.

Well, you've claimed that I'm wrong about something, and I'd appreciate
you backing that up with some evidence. I've backed up my side of
things above. It's not like this is a matter of opinion, and it *is*
important that people reading this thread can get a definitive answer -
it can easily affect whether or not they write correct code, as shown
above.
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
I did not discuss that and don't have in any way an other opinion. Why are
you forever proving things that I don't deny.

Well, you said:

<quote>
As it had been a "normal" reference type the object would in my idea
not be garbaged.
</quote>

I've shown that a "normal" reference type *can* be garbage collected.
If that's not what you meant, you should be clearer about what you're
talking about.
I only say that a string is an in the method created object, while non
immutable objects are just references, if they ain't created new.

Where do you get this strange idea that strings behave differently
though? String literals are slightly different, in that they're kept in
a pool somewhere so won't be garbage collected until the application
domain is unloaded, but no-one's mentioned literals in this thread.

I still don't know what you mean by "an in the method created object" -
but strings definitely behave like other objects. If I call:

string x = new string ('y', 10);

that's created a new object which can be garbage collected like any
other. The value of x is just a reference in exactly the same way as it
would be in:

object x = new object();

Perhaps it's best to make this concrete, and go back to my original
example. I'll fill in GrabSomeLongString. How many objects do you
believe are created in the following code:



void Foo()
{
string x = GrabSomeLongString();
Console.WriteLine (x.Length);

// Lots more code here

// Nothing referring to x

// End of method
}


string GrabSomeLongString()
{
return new string ('z', 1000);
}


I believe there's *one* object created, a string, which the variable x
refers to. After Console.WriteLine (x.Length), that string variable is
eligible for garbage collection.

So, how many objects do you think are created, and when do you believe
they're eligible for GC?
 
C

Cor Ligthert [MVP]

Jon,

Read my whole post,

The first object A from this reply I have showed you is not garbaged as the
MyJonObject is not instanced in this method. The second will, because it
holds outside the method no reference anymore.

object A = MyJonObject;
is different from
string A = MyJonObject.ToString();

And please keep answers by what I wrote; not what you have written that *I*
wrote; if we search on how many times you did that and how many times I
have asked you that when you don't understand my replies to ask specify what
I meant than we get endless messages. Not only by me by the way. I am
writting here mostly in a style expectiong that people are proffesionals not
amateurs in development and only need few words.

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
Read my whole post,

The first object A from this reply I have showed you is not garbaged as the
MyJonObject is not instanced in this method. The second will, because it
holds outside the method no reference anymore.

object A = MyJonObject;
is different from
string A = MyJonObject.ToString();

You introduced that example *after* contradicting my earlier example,
and introduced the example for no well-explained reason.

Note, however, that *again* there is nothing magical about strings
here. If you had written:

SomeOtherType x = MyJonObject.CreateSomeOtherType();

that would be exactly parallel to

string A = MyJonObject.ToString();


In other words, the fact that I used a string type is irrelevant, and
the fact that strings are immutable is irrelevant to their garbage
collection.


To make things clear:

a) there is no difference between strings and other reference types in
terms of whether variables hold reference

b) in my first example, contrary to your reply, what I was showing most
certainly *was* a reference.
And please keep answers by what I wrote; not what you have written that *I*
wrote;

I quoted your post exactly.
if we search on how many times you did that and how many times I
have asked you that when you don't understand my replies to ask specify what
I meant than we get endless messages. Not only by me by the way. I am
writting here mostly in a style expectiong that people are proffesionals not
amateurs in development and only need few words.

You are writing here in a style which is *frequently* hard to
understand - and not just by me.


Now, you have said that you believe I am wrong. Please state *exactly*,
in precise technical terms, in what way any of what I have posted in
this thread is wrong.
 

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