473,231 Members | 1,747 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,231 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 1587
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: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

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.