473,322 Members | 1,736 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,322 software developers and data experts.

Garbage Collection and unreferenced local variable

Hi all,
I have a question, in the following code:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());
}

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

TestClass instance x is created in the scope of the {} braces, so after the
closing brace x goes out of scope and it is not possible to reference it any
more. I would think that x should not be considered to be a root for garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.

So my question is, are the {} not considered to dictate garbage collection,
I would hope so, but it does not seem the case, below is the code that does
call the finalizer:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());

x = null;
}

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

Thanks
dniml.
Nov 28 '06 #1
9 3700
My understanding is that you can't make it finalize anything. You can
invoke the GC, but all that does is ask it to see if it thinks there's
a need to recover used memory. The nearest you can get is to use
IDispose, which still won't clean up, but does give you a sort of
determanistic way to tidy up as the object goes out of scope. It
doesn't happen automatically of course, you have to do it manually, or
use the object in a using block.
dotnetismylife wrote:
Hi all,
I have a question, in the following code:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());
}

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

TestClass instance x is created in the scope of the {} braces, so after the
closing brace x goes out of scope and it is not possible to reference it any
more. I would think that x should not be considered to be a root for garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.

So my question is, are the {} not considered to dictate garbage collection,
I would hope so, but it does not seem the case, below is the code that does
call the finalizer:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());

x = null;
}

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

Thanks
dniml.
Nov 28 '06 #2
Hi DeveloperX,
once the object goes out of scope and you forcefully call the GC on all
generations the finalizer should be called (if the object has one) since my
understanding is that the GC will kick off the finalize queue thread, and
the finalizer is deterministically being called in the second code sample
when the variable is explicitly set to null, so I am not sure why I have to
set it to null, when it is already out of scope in terms if the {}.

"DeveloperX" wrote:
My understanding is that you can't make it finalize anything. You can
invoke the GC, but all that does is ask it to see if it thinks there's
a need to recover used memory. The nearest you can get is to use
IDispose, which still won't clean up, but does give you a sort of
determanistic way to tidy up as the object goes out of scope. It
doesn't happen automatically of course, you have to do it manually, or
use the object in a using block.
dotnetismylife wrote:
Hi all,
I have a question, in the following code:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());
}

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

TestClass instance x is created in the scope of the {} braces, so after the
closing brace x goes out of scope and it is not possible to reference it any
more. I would think that x should not be considered to be a root for garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.

So my question is, are the {} not considered to dictate garbage collection,
I would hope so, but it does not seem the case, below is the code that does
call the finalizer:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());

x = null;
}

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

Thanks
dniml.

Nov 28 '06 #3
Yes true, but that's the whole point of the GC, it only does the
reclaimation and thus finalise when it's good and ready, you can't
force it, you can simply ask it if it thinks there's something it needs
to do. The mantra you will hear over and over again is never rely on a
finalizer to do anything.
You're right it will be marked as reclaimable as it goes out of scope
as you leave the inner {} but that doesn't mean the GC will do anything
about it unless it feels like it based on available resources, what
colour socks you're wearing and so on.
dotnetismylife wrote:
Hi DeveloperX,
once the object goes out of scope and you forcefully call the GC on all
generations the finalizer should be called (if the object has one) since my
understanding is that the GC will kick off the finalize queue thread, and
the finalizer is deterministically being called in the second code sample
when the variable is explicitly set to null, so I am not sure why I have to
set it to null, when it is already out of scope in terms if the {}.

"DeveloperX" wrote:
My understanding is that you can't make it finalize anything. You can
invoke the GC, but all that does is ask it to see if it thinks there's
a need to recover used memory. The nearest you can get is to use
IDispose, which still won't clean up, but does give you a sort of
determanistic way to tidy up as the object goes out of scope. It
doesn't happen automatically of course, you have to do it manually, or
use the object in a using block.
dotnetismylife wrote:
Hi all,
I have a question, in the following code:
>
using System;
using System.Diagnostics;
>
namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}
>
~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}
>
class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();
>
//Keep compiler honest
Debug.WriteLine(x.ToString());
}
>
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
>
TestClass instance x is created in the scope of the {} braces, so after the
closing brace x goes out of scope and it is not possible to reference it any
more. I would think that x should not be considered to be a root for garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.
>
So my question is, are the {} not considered to dictate garbage collection,
I would hope so, but it does not seem the case, below is the code that does
call the finalizer:
>
using System;
using System.Diagnostics;
>
namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}
>
~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}
>
class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();
>
//Keep compiler honest
Debug.WriteLine(x.ToString());
>
x = null;
}
>
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
>
Thanks
dniml.
Nov 28 '06 #4
dotnetismylife wrote:
[...] so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.

So my question is, are the {} not considered to dictate garbage collection,
I would hope so, but it does not seem the case, below is the code that does
call the finalizer:
Is this a Debug or Release build you're testing? They will behave
differently in this regard, IIRC.
Regards,

Matt

Nov 28 '06 #5
Hi,

I don't think, that the GC will take any notice of the braces. It only looks
if the variable is still used. In a Release build, I guess, the instance
will be finalized on the GC even without the braces. In a debug build it
holds the variable alife for some debugging tool, wich might inspect it. Or
the executionpoint might be set into the braces while a debugging session.

"dotnetismylife" <do************@discussions.microsoft.comschrieb im
Newsbeitrag news:DD**********************************@microsof t.com...
Hi all,
I have a question, in the following code:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());
}

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

TestClass instance x is created in the scope of the {} braces, so after
the
closing brace x goes out of scope and it is not possible to reference it
any
more. I would think that x should not be considered to be a root for
garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.

So my question is, are the {} not considered to dictate garbage
collection,
I would hope so, but it does not seem the case, below is the code that
does
call the finalizer:

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Debug.WriteLine("TestClass constructor");
}

~TestClass()
{
Debug.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
{
TestClass x = new TestClass();

//Keep compiler honest
Debug.WriteLine(x.ToString());

x = null;
}

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

Thanks
dniml.

Nov 28 '06 #6
Oh I see your point now, I missed the subtle distinction between the
two listings and hadn't notice you didn't set the variable to null in
the first. As you can't do
void method()
{
int x = 0;
{
int x = 1;
}
}

I assume the variable is still in scope until the function exits.
Apologies for the misunderstanding.

Nov 28 '06 #7
dotnetismylife wrote:
TestClass instance x is created in the scope of the {} braces, so after the
closing brace x goes out of scope and it is not possible to reference it any
more. I would think that x should not be considered to be a root for garbage
collection, so when GC.Collect is called the GC would see that nothing
references this instance and call the finalizer on the instance. However
this does not happen, the finalizer is not called, however if I put an
explicit assignment of null to x i.e. "x=null;" inside the {} then it's
finalizer is called.
This appears to be an artifact of debug mode and/or running the
release version within VS. When I replace the calls to Debug.WriteLine
with calls to Console.WriteLine, add a WriteLine to let me know when
WaitForPendingFinalizers is called, compile in release mode, and run
the exe from a Windows Explorer window, "TestClass finalizer" does
appear before WaitForPendingFinalizers returns.

For that matter, it works as expected if I comment out the braces
around x.

Bottom line: In normal operation, a variable that is no longer used is
eligible for garbage collection.

//

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
class TestClass
{
public TestClass()
{
Console.WriteLine("TestClass constructor");
}

~TestClass()
{
Console.WriteLine("TestClass finalizer");
}
}

class Program
{
static void Main(string[] args)
{
//{
TestClass x = new TestClass();

//Keep compiler honest
Console.WriteLine(x.ToString());
//}

GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("GC.WaitForPendingFinalizers() has
returned");
Console.ReadLine();
}
}
}

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 28 '06 #8
dotnetismylife wrote:
>
>TestClass instance x is created in the scope of the {} braces, so
after the closing brace x goes out of scope and it is not possible to
reference it any more. I would think that x should not be considered
to be a root for garbage collection, so when GC.Collect is called the
GC would see that nothing references this instance and call the
finalizer on the instance. However this does not happen, the
finalizer is not called, however if I put an explicit assignment of
null to x i.e. "x=null;" inside the {} then it's finalizer is called.
This appears to be an artifact of debug mode and/or running the
release version within VS. When I replace the calls to Debug.WriteLine
with calls to Console.WriteLine, add a WriteLine to let me know when
WaitForPendingFinalizers is called, compile in release mode, and run
the exe from a Windows Explorer window, "TestClass finalizer" does
appear before WaitForPendingFinalizers returns.
It's actually caused by a little-known option in Visual Studio that disables
JIT optimizations while debugging code that has been optimized (e.g. in Release
mode). To turn it off, follow these steps:

1. Selection "Options..." from the "Tools" menu to display the Options dialog.
2. In the Options dialog, select the "Debugging -General" page.
3. Scroll all the way to the bottom and uncheck the "Suppress JIT optimization
on module load (Managed only)" box.
4. In addition, uncheck the "Enable Just My Code (Managed only)" box. Otherwise,
VS will complain when you debug the app.
5. Click OK to close the dialog and accept the changes.

Now, if you debug your Release mode app, it'll function properly.

Best Regards,
Dustin Campbell
Developer Express Inc.
Nov 28 '06 #9
DeveloperX <nn*****@operamail.comwrote:
Oh I see your point now, I missed the subtle distinction between the
two listings and hadn't notice you didn't set the variable to null in
the first. As you can't do
void method()
{
int x = 0;
{
int x = 1;
}
}

I assume the variable is still in scope until the function exits.
Apologies for the misunderstanding.
The variable is no longer treated as a GC root as soon as the JIT
notices that it will no longer be read.

For instance:

public void Foo()
{
object o = new object();

for (int i=0; i < 100000; i++)
{
// Do stuff here not related to o
}
}

During the loop, when not running in a debugger, the object created in
the first line is eligible for garbage collection.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 28 '06 #10

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

Similar topics

11
by: Alzane | last post by:
I'm new to C++ programming. I have an exercise that I have written code for but getting warnings. Can I get some help? #include "stdafx.h" #include <string.h> #include <stdio.h> #include...
10
by: pachanga | last post by:
The Hans-Boehm garbage collector can be successfully used with C and C++, but not yet a standard for C++.. Is there talks about Garbage Collector to become in the C++ standard?
4
by: bkazlak | last post by:
Hello, I have a quick question might help me understand garbage collection. let's say I'm having a static collection of objects in one class, so this collection should be cached and present...
3
by: cbmeeks | last post by:
I think I know the answer to this but I would like to confim. I have an app where I've built a custom DataSet containing several DataTables. Within the DataTables, I sometimes check for...
56
by: Johnny E. Jensen | last post by:
Hellow I'am not sure what to think about the Garbage Collector. I have a Class OutlookObject, It have two private variables. Private Microsoft.Office.Interop.Outlook.Application _Application =...
350
by: Lloyd Bonafide | last post by:
I followed a link to James Kanze's web site in another thread and was surprised to read this comment by a link to a GC: "I can't imagine writing C++ without it" How many of you c.l.c++'ers use...
3
by: from.future.import | last post by:
Hi, I encountered garbage collection behaviour that I didn't expect when using a recursive function inside another function: the definition of the inner function seems to contain a circular...
12
by: =?Utf-8?B?Y2hpbmFzcHJpdA==?= | last post by:
static tc gto; public class tc { public int a=99; ~tc() { a=-1; //set breakpoint 1 gto=this;
158
by: pushpakulkar | last post by:
Hi all, Is garbage collection possible in C++. It doesn't come as part of language support. Is there any specific reason for the same due to the way the language is designed. Or it is...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
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...

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.