C# memory leak??!!!!!

M

Martin Law

Hi all,

I am using both "perfmon" and GC.GetTotalMemory() to keep track of the heap
memory space usage of the following simple program. Both ways suggest that
the garbage collector cannot reclaim all "dead" memory. Any idea?

using System;

using System.IO;

namespace test_leak

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class Class1

{

static void t0()

{

System.Collections.ArrayList ar = new System.Collections.ArrayList();

for (int i=0; i<1000; i++) ar.Add(i);

// GC.Collect();

//Console.WriteLine("6 Memory used now is {0}", GC.GetTotalMemory(true));

}



/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

int i = 0;

GC.Collect();

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

t0();

System.GC.WaitForPendingFinalizers();

GC.Collect();

i ++;

GC.Collect();

//Console.WriteLine("************************************");

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

return;

}

}

}





and the output is





Memory used now is 34924
Memory used now is 35308






So some memory is lost. :-(

While this sounds small, this can really add up. Sigh....

Can anybody give me a hand? Many thanks!
 
M

Martin Law

Hi. Thank you for your response.
What you have described is what I expect the garbage collector does.... This
somewhat contradicts with what I observe, though....

In my code example below, I have called System.GC.WaitForPendingFinalizers()
which should wait for all finalizers to finish.

I am kind of frustrated right now, as I have a program that runs long
finally eats up all available memory (1G), and I have no idea why this is
the case.

One possible reason is that I am still referencing objects that are no
longer useful to me, but it is hard to find them out... Sign....



Andre said:
Doing a GC.Collect() doesn't guarantee that all memory will be
collected. Some objects might be waiting for finalization and so they'll
be collected once they're finalized. This by no means implies that
memory is being lost or that 'lost memory will be added up'. You can
read more about the garbage collector on MSDN. To sum it up, just know
that "dead" memory will be reclaimed on its own and that the Garbage
collector has a completely undeterministic behavior and it is advised
not to do a manual GC.Collect() (as it interferes with runtime
measurements performed by the GC to know when to collect and when not
to). Don't worry, your memory will be collected in case your program
runs any longer or when objects in memory have all "weak" or "strong"
references removed (i.e objects in memory have no more references from
the ROOTS or other objects that are accessible from ROOT objects or
variables).


-Andre



Martin said:
Hi all,

I am using both "perfmon" and GC.GetTotalMemory() to keep track of the heap
memory space usage of the following simple program. Both ways suggest that
the garbage collector cannot reclaim all "dead" memory. Any idea?

using System;

using System.IO;

namespace test_leak

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class Class1

{

static void t0()

{

System.Collections.ArrayList ar = new System.Collections.ArrayList();

for (int i=0; i<1000; i++) ar.Add(i);

// GC.Collect();

//Console.WriteLine("6 Memory used now is {0}", GC.GetTotalMemory(true));

}



/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

int i = 0;

GC.Collect();

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

t0();

System.GC.WaitForPendingFinalizers();

GC.Collect();

i ++;

GC.Collect();

//Console.WriteLine("************************************");

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

return;

}

}

}





and the output is





Memory used now is 34924
Memory used now is 35308






So some memory is lost. :-(

While this sounds small, this can really add up. Sigh....

Can anybody give me a hand? Many thanks!
 
J

Jon Skeet

Martin Law said:
I am using both "perfmon" and GC.GetTotalMemory() to keep track of the heap
memory space usage of the following simple program. Both ways suggest that
the garbage collector cannot reclaim all "dead" memory. Any idea?

I believe what you're seeing is the fact that before you call
GetTotalMemory(true) you haven't done any console output, or called
(implicitly) String.Format which occurs afterwards - there's a lot of
code to be JITted and potentialy resources to be loaded. If you put a
simple
Console.WriteLine ("{0}", 1);
before the first memory output, you'll see things change quite a lot -
and then there's the loading and JITting of ArrayList as well.
Basically all you're seeing is the memory used by the JITter and the
type loader. Nothing to worry about.
 
T

Thomas Tomicek [MVP]

Ressource leak?

Object leak?

The GC can not prevent all kinds of memory leaks - if just guarantees
unreachable memory is collected. You can easily create memory that is never
unreachable.

Have you ever tried a memory profiler? If would tell you what object types
consume what amount of memory. THey cost a ton of money, u you can usually
get a trial for free, and this is all you need. AND they aere worth the
money.

--
Regards

Thomas Tomiczek
THONA Software & Consulting Ltd.
(Microsoft MVP C#/.NET)

Martin Law said:
Hi. Thank you for your response.
What you have described is what I expect the garbage collector does.... This
somewhat contradicts with what I observe, though....

In my code example below, I have called System.GC.WaitForPendingFinalizers()
which should wait for all finalizers to finish.

I am kind of frustrated right now, as I have a program that runs long
finally eats up all available memory (1G), and I have no idea why this is
the case.

One possible reason is that I am still referencing objects that are no
longer useful to me, but it is hard to find them out... Sign....



Andre said:
Doing a GC.Collect() doesn't guarantee that all memory will be
collected. Some objects might be waiting for finalization and so they'll
be collected once they're finalized. This by no means implies that
memory is being lost or that 'lost memory will be added up'. You can
read more about the garbage collector on MSDN. To sum it up, just know
that "dead" memory will be reclaimed on its own and that the Garbage
collector has a completely undeterministic behavior and it is advised
not to do a manual GC.Collect() (as it interferes with runtime
measurements performed by the GC to know when to collect and when not
to). Don't worry, your memory will be collected in case your program
runs any longer or when objects in memory have all "weak" or "strong"
references removed (i.e objects in memory have no more references from
the ROOTS or other objects that are accessible from ROOT objects or
variables).


-Andre



Martin said:
Hi all,

I am using both "perfmon" and GC.GetTotalMemory() to keep track of the heap
memory space usage of the following simple program. Both ways suggest that
the garbage collector cannot reclaim all "dead" memory. Any idea?

using System;

using System.IO;

namespace test_leak

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class Class1

{

static void t0()

{

System.Collections.ArrayList ar = new System.Collections.ArrayList();

for (int i=0; i<1000; i++) ar.Add(i);

// GC.Collect();

//Console.WriteLine("6 Memory used now is {0}", GC.GetTotalMemory(true));

}



/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

int i = 0;

GC.Collect();

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

t0();

System.GC.WaitForPendingFinalizers();

GC.Collect();

i ++;

GC.Collect();

//Console.WriteLine("************************************");

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

return;

}

}

}





and the output is





Memory used now is 34924
Memory used now is 35308






So some memory is lost. :-(

While this sounds small, this can really add up. Sigh....

Can anybody give me a hand? Many thanks!
 
R

Rob Tillie

Could this be because you forgot to call a dispose method on some object?
( On the real app which loses 1 GB, not the demo)

Greetz,
-- Rob.
omg are you serious there is a memory leak within c#???

this is bad.

-----Original Message-----
Hi all,

I am using both "perfmon" and GC.GetTotalMemory() to keep track of
the heap memory space usage of the following simple program. Both
ways suggest that the garbage collector cannot reclaim all "dead"
memory. Any idea?

using System;

using System.IO;

namespace test_leak

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class Class1

{

static void t0()

{

System.Collections.ArrayList ar = new System.Collections.ArrayList();

for (int i=0; i<1000; i++) ar.Add(i);

// GC.Collect();

//Console.WriteLine("6 Memory used now is {0}",
GC.GetTotalMemory(true));

}



/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main(string[] args)

{

int i = 0;

GC.Collect();

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

t0();

System.GC.WaitForPendingFinalizers();

GC.Collect();

i ++;

GC.Collect();

//Console.WriteLine ("************************************");

Console.WriteLine("Memory used now is {0}", GC.GetTotalMemory(true));

return;

}

}

}





and the output is





Memory used now is 34924
Memory used now is 35308






So some memory is lost. :-(

While this sounds small, this can really add up. Sigh....

Can anybody give me a hand? Many thanks!






.
 
M

Martin Law

Thank you for all your responses.
With the help of a tool showing the heap memory, I discover the culprit is
the following statement. (I am using a different regular expressions as
listed below in my real program.)

string s1 = System.Text.RegularExpressions.Regex.Replace(s2, "a", "");

I have called this stement thousands of times. According to the
documentation, this static method should create a Regex object and perform
the replacement. When this statement ends, the garbage collector should be
able to collect and free the corresponding resources. However, it does not
seem to be the case. At the end of my program, there are hundres of
megabytes of memory belonging to Regex.

Obviously, if I want to do the replacement so many times, I should have
created a Regex object instead of using the static version of the method....

I get rid of the regular expression thing and write a for-loop to do my
processing instead. The memory leak problem, as expected, disappears.

Is this a known issue? If not, where should I report it?

Thanks!!!!


Martin
 

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