473,385 Members | 1,492 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

=?Utf-8?Q?garbage_collect=E2=80=94=E2=80=94is_a_bug=EF=B C=9F?=

static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute at
the second time clicking.why?
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while to.a=99,why?
Aug 31 '08 #1
12 1593
On Sat, 30 Aug 2008 17:34:00 -0700, chinasprit
<ch********@discussions.microsoft.comwrote:
[...]
two problems:
click button once,it seem the ~tc() not execute at all.and it will
excute at
the second time clicking.why?
Are you using a debug build or an optimized build? Have you tried a
similar test without a debugger (which could affect reachability of
objects)?

It's true that the object referenced by "to" is eligible for collection
when you call GC.Collect(). But I'm not aware of any _requirement_ that
it be collected. And when debugging, or for a debug build, it very well
might not be.
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while
to.a=99,why?
Why not? The object referenced by "gto" has had its "a" member set to -1,
which is why you get that value. The obejct referenced by "to" has not,
which is why you get 99 instead. Since your first click of the button
already demonstrated that the object referenced by the local variable
isn't being collected, you shouldn't be surprised that it's also not
collected the second time you click the button.

Please see attached below a console application that is essentially the
same test you're doing, but as a true, useful, concise-but-complete code
example. When I run it under the debugger, the object is never finalized
until after the called method returns. When I compile it as a "Debug"
build, that behavior also occurs even when run standalone, without the
debugger.

But when I compile it as a "Release" build and run it standalone, the
object is released, just as it's _allowed_ to be (note difference between
"required" and "allowed").

Now, all that said...there's practically no situation in which you should
_care_ if or when an object is finalized or collected. So, even if this
were a bug in the GC (and it's not), it's not something that should matter
to your own code. If you've got code where it does matter, you've got a
basic design flaw that you should fix.

Pete
using System;

namespace TestUnreachableLocalGC
{
class Program
{
class A
{
static A _a;

int i = 1;

~A()
{
i = -1;
if (_a == null)
{
_a = this;
}
}
}

static void Test()
{
A a = new A();
WeakReference wrA = new WeakReference(a);

GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine("object still valid: " + wrA.IsAlive);
}

static void Main(string[] args)
{
Test();
Console.ReadLine();
Test();
Console.ReadLine();
}
}
}
Aug 31 '08 #2
"chinasprit" <ch********@discussions.microsoft.comwrote in message
news:20**********************************@microsof t.com...
static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute
at
the second time clicking.why?
I remember reading something about the GC disposing objects on the first run
(if they have IDispose) and destroying them on the second run. If that is
the case then your second point makes sense because you're looking at 2
different objects and the second object has not been disposed yet.
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while
to.a=99,why?


Aug 31 '08 #3
Michael C <mi**@nospam.comwrote:
I remember reading something about the GC disposing objects on the first run
(if they have IDispose) and destroying them on the second run. If that is
the case then your second point makes sense because you're looking at 2
different objects and the second object has not been disposed yet.
The garbage collector itself doesn't know about IDisposable at all. It
calls finalizers, which may in turn call Dispose, but it doesn't call
Dispose directly itself.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 31 '08 #4
chinasprit <ch********@discussions.microsoft.comwrote:
static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute at
the second time clicking.why?
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while to.a=99,why?
When you run in a debugger, local variables prevent garbage collection
until the end of the message (or at least the scope; I can't remember
off hand). Change from using breakpoints to some other diagnostic (e.g.
a message box) and run without debugging - you'll get the behaviour you
expect.

Alternatively, put "to = null;" before the call to GC.Collect().

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 31 '08 #5
On Sat, 30 Aug 2008 23:33:24 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
When you run in a debugger, local variables prevent garbage collection
until the end of the message (or at least the scope; I can't remember
off hand). Change from using breakpoints to some other diagnostic (e.g.
a message box) and run without debugging - you'll get the behaviour you
expect.
In a "Release" build. At least in my test, the "Debug" build didn't
bother to collect the object until after the method exited. The compiled
IL was basically the same, but obviously it's treated differently. Either
the JIT compiler generates different output, or the garbage collector
itself handles the decision-making differently for "Debug" and "Release"
builds (I didn't bother to investigate any further than that).

Pete
Aug 31 '08 #6
Peter Duniho <Np*********@nnowslpianmk.comwrote:
On Sat, 30 Aug 2008 23:33:24 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
When you run in a debugger, local variables prevent garbage collection
until the end of the message (or at least the scope; I can't remember
off hand). Change from using breakpoints to some other diagnostic (e.g.
a message box) and run without debugging - you'll get the behaviour you
expect.

In a "Release" build. At least in my test, the "Debug" build didn't
bother to collect the object until after the method exited. The compiled
IL was basically the same, but obviously it's treated differently. Either
the JIT compiler generates different output, or the garbage collector
itself handles the decision-making differently for "Debug" and "Release"
builds (I didn't bother to investigate any further than that).
Slightly more information - I think it's the optimisation side of
things, not the debug information. Here's a very short program to
demonstrate it:

using System;

class Test
{
~Test()
{
Console.WriteLine("Finalized");
}

static void Main()
{
Test t = new Test();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Hit return...");
Console.ReadLine();
}
}

Compiling with "/debug+ /o-" I don't see the finalization message until
after I've hit return. Compiling with "/debug+ /o+" I see it
immediately.

The IL is significantly different for the optimised version - it
doesn't store the value in the local variable at all, just pops the
constructed value from the stack immediately.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 31 '08 #7
On Sun, 31 Aug 2008 01:03:19 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
[...]
Slightly more information - I think it's the optimisation side of
things, not the debug information.
When I have more time, I'll look again. But for now, I'm going with "c,
both of the above". That is...
[...]
The IL is significantly different for the optimised version - it
doesn't store the value in the local variable at all, just pops the
constructed value from the stack immediately.
The IL I looked at definitely wasn't significantly different for the
"Release" build. In fact, other than not having the "nop" instructions
the "Debug" build had, it was basically the same.

My current theory: you can explicitly set optimization on the C# compiler
settings that does make this happen. But the JIT compiler _also_ does
optimizations that can cause this to happen, even though the default
optimization settings that VS is using (for me, anyway) for the "Release"
build wouldn't otherwise.

Of course, it begs an entirely unrelated question: who does optimization
better? The C# compiler? The JIT compiler? Or some combination?

Pete
Aug 31 '08 #8
Peter Duniho <Np*********@nnowslpianmk.comwrote:

<snip>
Of course, it begs an entirely unrelated question: who does optimization
better? The C# compiler? The JIT compiler? Or some combination?
The C# compiler doesn't do very much of it, which makes sense IMO -
having a good JIT optimiser benefits *all* languages. Obviously there's
a cost at execution time, of course - and a bit more tweakability would
be welcome there (e.g. as an app.config option to say "feel free to
take a long time to optimise the heck out of this code").

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 31 '08 #9
Michael C wrote:
"chinasprit" <ch********@discussions.microsoft.comwrote in message
news:20**********************************@microsof t.com...
>static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute
at
the second time clicking.why?

I remember reading something about the GC disposing objects on the first run
(if they have IDispose) and destroying them on the second run.
Not exactly.

If an object that is unreachable has a finalizer, it will be placed on
the freachable queue, where a background thread will execute the
finalizer. After the finalizer has been run, the object can be collected
just like any other object.
If that is
the case then your second point makes sense because you're looking at 2
different objects and the second object has not been disposed yet.
>the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while
to.a=99,why?



--
Göran Andersson
_____
http://www.guffa.com
Aug 31 '08 #10
chinasprit wrote:
static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute at
the second time clicking.why?
Calling GC.Collect doesn't guarantee that a garbage collection is
actually performed. If the garbage collector feels that there is too
little to be done, it can just skip the collection.

Also, as you are running in debug mode, the garbage collector looks at
the usage of variables quite differently. In release mode, the object
that you create immediately becomes unreachable, as the variable "to" is
never used any more. In debug mode, the "to" variable is considered in
use it's entire scope, i.e. as long as the debugger can display it's
value, so the object can't be collected until after exiting the method.
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while to.a=99,why?
As the newly created object can't be collected until the method exits,
to.a can never be anything but 99 in debug mode.

--
Göran Andersson
_____
http://www.guffa.com
Aug 31 '08 #11
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
chinasprit <ch********@discussions.microsoft.comwrote:
>static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute
at
the second time clicking.why?
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while
to.a=99,why?

When you run in a debugger, local variables prevent garbage collection
until the end of the message (or at least the scope; I can't remember
off hand). Change from using breakpoints to some other diagnostic (e.g.
a message box) and run without debugging - you'll get the behaviour you
expect.

Alternatively, put "to = null;" before the call to GC.Collect().

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

From what I've seen, the debugger holds local variables around until they go
out of scope. This is why you can review a local variable's value even
after the last reference to it in your code. This is a functional
requirement of any descent debugger. Since the variable is still accessible
through the debugger, it can't be garbage collected. The bug would have
been the GC reclaiming it before the end of the visible scope.

In release code, the compile should be able to determine using lexical
analysis when to insert a "to = null" for you so that the GC can reclaim the
memory.

Mike Ober.
Aug 31 '08 #12
Michael D. Ober wrote:
In release code, the compile should be able to determine using lexical
analysis when to insert a "to = null" for you so that the GC can reclaim
the memory.
Actually, there is no code inserted to clear the reference, as that is
not needed. The garbage collector knows where the variables are used,
and can determine that the object is unreachable eventhough the variable
still contains a reference to it.

--
Göran Andersson
_____
http://www.guffa.com
Aug 31 '08 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: sinasalek | last post by:
i have a problem with MySQL 4.1.x and UTF8. in version 4.0, i'm using html forms with utf8 charset for inserting unicode strings. but in version 4.1.x it is not working! if i change the charset of...
5
by: Richard Lewis | last post by:
Hi there, I'm having a problem with unicode files and ftplib (using Python 2.3.5). I've got this code: xml_source = codecs.open("foo.xml", 'w+b', "utf8") #xml_source = file("foo.xml",...
6
by: Spamtrap | last post by:
I only work in Perl occasionaly, and have been searching for a solution for a conversion, and everything I found seems much too complex. All I need to do is take a simple text file and copy...
1
by: ryang | last post by:
I am trying to understand how to work with Unicode in Perl. I have read the relevant man pages (perluniintro, perlunicode, etc.) and have written severl scripts to test/verifiy my understanding. ...
0
by: Sagi Bashari | last post by:
Hello, I would like to know the status of the UTF8 support in MySQL 4.1. I tried to create a table using utf8 charset, and inserting hebrew text into it. it seems like it still treats this...
0
by: JJ | last post by:
Hi, I have a little, big, boring problem :) I have a utf8 txt file to import in a MySQL db, cause I must create a web-application in PHP for reading this information on-line. I have create...
3
by: hunterb | last post by:
I have a file which has no BOM and contains mostly single byte chars. There are numerous double byte chars (Japanese) which appear throughout. I need to take the resulting Unicode and store it in a...
4
by: H Lee | last post by:
Hi, I'm an XML newbie, and not sure if this is the appropriate newsgroup to post my question, so feel free to suggest other newgroups where I should post this message if this is the case. I'm...
7
by: amygdala | last post by:
Hi, I'm trying to let PHP write a 'sitemap.xml' sitemap for Google and other searchengines. It's working, except that the content in the XML file doesn't seem to be UTF8. (Which it should be,...
39
by: alex | last post by:
I've converted a latin1 database I have to utf8. The process has been: # mysqldump -u root -p --default-character-set=latin1 -c --insert-ignore --skip-set-charset mydb mydb.sql # iconv -f...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.