I am trying to track a suspected memory leak in an application I'm writing
and through repeated simplification of my project, I have found the
following which is quite easily replicated should you be prepared to give
me
5 minutes of your time...

Create a new C# (Probably the same in VB dotNET but I've not tried it)
Windows application with 2 forms, the default form -Form1 and one other
one.
that has a bunch of controls on it (say 20 buttons, 20 labels and a
DataGrid) - Form2.

On the default form, add a button to display the second form with some code
like:

private void button1_Click(object sender, System.EventArgs e)
{
using (form2 formTwo = new form2())
{
form2.ShowDialog();
}
}

also on Form1 add a label, and a timer that updates the label text as
follows (updates every 5 seconds -Interval = 5000-):

private void timer1_Tick(object sender, System.EventArgs e)
{
label1.Text = GC.GetTotalMemory(False);
}

and finally a button that forces a Garbage Collection:

private button2_Click(object sender, System.EventArgs e)
{
GC.Collect();
}

OK, my question/query is this, if I repeatedly click the button to open the
second form, then close the second form, click the button, close the form
etc. about 20-30 times, the display of GetTotalMemory seems to keep going
up, and even after forcing Garbage Collections, never seems to get fully
reclaimed. Should I care? and if I should, what (if anything) can I do
about
it?

I would really appreciate an answer from someone who understands these
things...

Thanks a lot,

Chris.

Re: GC, Should I care? by Jsp

Jsp
Fri Apr 15 08:38:01 CDT 2005

Use "SetProcessWorkingSetSize(-1,-1)" from kernel32.dll instead.

"Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
>
> I am trying to track a suspected memory leak in an application I'm writing
> and through repeated simplification of my project, I have found the
> following which is quite easily replicated should you be prepared to give
> me
> 5 minutes of your time...
>
> Create a new C# (Probably the same in VB dotNET but I've not tried it)
> Windows application with 2 forms, the default form -Form1 and one other
> one.
> that has a bunch of controls on it (say 20 buttons, 20 labels and a
> DataGrid) - Form2.
>
> On the default form, add a button to display the second form with some
> code
> like:
>
> private void button1_Click(object sender, System.EventArgs e)
> {
> using (form2 formTwo = new form2())
> {
> form2.ShowDialog();
> }
> }
>
> also on Form1 add a label, and a timer that updates the label text as
> follows (updates every 5 seconds -Interval = 5000-):
>
> private void timer1_Tick(object sender, System.EventArgs e)
> {
> label1.Text = GC.GetTotalMemory(False);
> }
>
> and finally a button that forces a Garbage Collection:
>
> private button2_Click(object sender, System.EventArgs e)
> {
> GC.Collect();
> }
>
> OK, my question/query is this, if I repeatedly click the button to open
> the
> second form, then close the second form, click the button, close the form
> etc. about 20-30 times, the display of GetTotalMemory seems to keep going
> up, and even after forcing Garbage Collections, never seems to get fully
> reclaimed. Should I care? and if I should, what (if anything) can I do
> about
> it?
>
> I would really appreciate an answer from someone who understands these
> things...
>
> Thanks a lot,
>
> Chris.
>
>
>
>





Re: GC, Should I care? by Phil

Phil
Fri Apr 15 09:29:48 CDT 2005

If Form2 has a collection of controls on it, they've got Finalizers and
Dispose methods that aren't being called (because the only Dispose you're
calling is on Form2 itself). So it's possible that you have a queue of
Finalizers (for those controls) that haven't been called yet, and that queue
grows every time you instantiate a form2. The CLR Profiler should help you
see what's going on.
http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en
--
Phil Wilson
[Microsoft MVP-Windows Installer]

"Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
>
> I am trying to track a suspected memory leak in an application I'm writing
> and through repeated simplification of my project, I have found the
> following which is quite easily replicated should you be prepared to give
> me
> 5 minutes of your time...
>
> Create a new C# (Probably the same in VB dotNET but I've not tried it)
> Windows application with 2 forms, the default form -Form1 and one other
> one.
> that has a bunch of controls on it (say 20 buttons, 20 labels and a
> DataGrid) - Form2.
>
> On the default form, add a button to display the second form with some
> code
> like:
>
> private void button1_Click(object sender, System.EventArgs e)
> {
> using (form2 formTwo = new form2())
> {
> form2.ShowDialog();
> }
> }
>
> also on Form1 add a label, and a timer that updates the label text as
> follows (updates every 5 seconds -Interval = 5000-):
>
> private void timer1_Tick(object sender, System.EventArgs e)
> {
> label1.Text = GC.GetTotalMemory(False);
> }
>
> and finally a button that forces a Garbage Collection:
>
> private button2_Click(object sender, System.EventArgs e)
> {
> GC.Collect();
> }
>
> OK, my question/query is this, if I repeatedly click the button to open
> the
> second form, then close the second form, click the button, close the form
> etc. about 20-30 times, the display of GetTotalMemory seems to keep going
> up, and even after forcing Garbage Collections, never seems to get fully
> reclaimed. Should I care? and if I should, what (if anything) can I do
> about
> it?
>
> I would really appreciate an answer from someone who understands these
> things...
>
> Thanks a lot,
>
> Chris.
>
>
>
>



Re: GC, Should I care? by Chris

Chris
Fri Apr 15 09:54:02 CDT 2005

OK,

So should I override the Dispose method in Form2 and use it to call Dispose
on each of its controls, I was thinking of giving that a shot anyway.

Chris.


"Phil Wilson" <pdjwilson@nospam.cox.net> wrote in message
news:eFymFccQFHA.3704@TK2MSFTNGP12.phx.gbl...
> If Form2 has a collection of controls on it, they've got Finalizers and
> Dispose methods that aren't being called (because the only Dispose you're
> calling is on Form2 itself). So it's possible that you have a queue of
> Finalizers (for those controls) that haven't been called yet, and that
queue
> grows every time you instantiate a form2. The CLR Profiler should help you
> see what's going on.
>
http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en
> --
> Phil Wilson
> [Microsoft MVP-Windows Installer]
>
> "Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
> news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
> >
> > I am trying to track a suspected memory leak in an application I'm
writing
> > and through repeated simplification of my project, I have found the
> > following which is quite easily replicated should you be prepared to
give
> > me
> > 5 minutes of your time...
> >
> > Create a new C# (Probably the same in VB dotNET but I've not tried it)
> > Windows application with 2 forms, the default form -Form1 and one other
> > one.
> > that has a bunch of controls on it (say 20 buttons, 20 labels and a
> > DataGrid) - Form2.
> >
> > On the default form, add a button to display the second form with some
> > code
> > like:
> >
> > private void button1_Click(object sender, System.EventArgs e)
> > {
> > using (form2 formTwo = new form2())
> > {
> > form2.ShowDialog();
> > }
> > }
> >
> > also on Form1 add a label, and a timer that updates the label text as
> > follows (updates every 5 seconds -Interval = 5000-):
> >
> > private void timer1_Tick(object sender, System.EventArgs e)
> > {
> > label1.Text = GC.GetTotalMemory(False);
> > }
> >
> > and finally a button that forces a Garbage Collection:
> >
> > private button2_Click(object sender, System.EventArgs e)
> > {
> > GC.Collect();
> > }
> >
> > OK, my question/query is this, if I repeatedly click the button to open
> > the
> > second form, then close the second form, click the button, close the
form
> > etc. about 20-30 times, the display of GetTotalMemory seems to keep
going
> > up, and even after forcing Garbage Collections, never seems to get fully
> > reclaimed. Should I care? and if I should, what (if anything) can I do
> > about
> > it?
> >
> > I would really appreciate an answer from someone who understands these
> > things...
> >
> > Thanks a lot,
> >
> > Chris.
> >
> >
> >
> >
>
>



Re: GC, Should I care? by Stefan

Stefan
Fri Apr 15 10:12:01 CDT 2005


Chris Mayers wrote:
> OK,
>
> So should I override the Dispose method in Form2 and use it to call Dispose
> on each of its controls, I was thinking of giving that a shot anyway.
>
> Chris.

No, Control.Dispose disposes all child controls as well. Because every
form derives from Control, in disposes all it's children recursively.

HTH,
Stefan

>
>
> "Phil Wilson" <pdjwilson@nospam.cox.net> wrote in message
> news:eFymFccQFHA.3704@TK2MSFTNGP12.phx.gbl...
>
>>If Form2 has a collection of controls on it, they've got Finalizers and
>>Dispose methods that aren't being called (because the only Dispose you're
>>calling is on Form2 itself). So it's possible that you have a queue of
>>Finalizers (for those controls) that haven't been called yet, and that

The above is *not* true.

>
> queue
>
>>grows every time you instantiate a form2. The CLR Profiler should help you
>>see what's going on.
>>
>
> http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en
>
>>--
>>Phil Wilson
>>[Microsoft MVP-Windows Installer]
>>
>>"Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
>>news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
>>
>>>I am trying to track a suspected memory leak in an application I'm
>
> writing
>
>>>and through repeated simplification of my project, I have found the
>>>following which is quite easily replicated should you be prepared to
>
> give
>
>>>me
>>>5 minutes of your time...
>>>
>>>Create a new C# (Probably the same in VB dotNET but I've not tried it)
>>>Windows application with 2 forms, the default form -Form1 and one other
>>>one.
>>>that has a bunch of controls on it (say 20 buttons, 20 labels and a
>>>DataGrid) - Form2.
>>>
>>>On the default form, add a button to display the second form with some
>>>code
>>>like:
>>>
>>>private void button1_Click(object sender, System.EventArgs e)
>>>{
>>> using (form2 formTwo = new form2())
>>> {
>>> form2.ShowDialog();
>>> }
>>>}
>>>
>>>also on Form1 add a label, and a timer that updates the label text as
>>>follows (updates every 5 seconds -Interval = 5000-):
>>>
>>>private void timer1_Tick(object sender, System.EventArgs e)
>>>{
>>> label1.Text = GC.GetTotalMemory(False);
>>>}
>>>
>>>and finally a button that forces a Garbage Collection:
>>>
>>>private button2_Click(object sender, System.EventArgs e)
>>>{
>>> GC.Collect();
>>>}
>>>
>>>OK, my question/query is this, if I repeatedly click the button to open
>>>the
>>>second form, then close the second form, click the button, close the
>
> form
>
>>>etc. about 20-30 times, the display of GetTotalMemory seems to keep
>
> going
>
>>>up, and even after forcing Garbage Collections, never seems to get fully
>>>reclaimed. Should I care? and if I should, what (if anything) can I do
>>>about
>>>it?
>>>
>>>I would really appreciate an answer from someone who understands these
>>>things...
>>>
>>>Thanks a lot,
>>>
>>>Chris.
>>>
>>>
>>>
>>>
>>
>>
>
>

Re: GC, Should I care? by AMercer

AMercer
Fri Apr 15 10:31:04 CDT 2005

Re "So should I override ..", the answer is no, unless you are chasing a real
memory leak. if you want to see memory reclaimed, then use
GC.WaitForPendingFinalizers in cunjunction with GC.Collect. Once upon a
time, while chasing a memory leak, I coded

Dim i As Integer
Dim l As Long
For i = 1 To 3
GC.Collect()
GC.WaitForPendingFinalizers()
l = GC.GetTotalMemory(True)
Next

My purpose was to coerce garbage collections so I could watch the memory
leak grow without the confusion of delayed garbage collections. When growth
stopped, I had fixed my memory leak. FYI the leak was my failure to
explicitly call Dispose for a context menu that I created in a non-standard
way.

The bottom line is that you don't need to worry about GC absent a problem
like a memory leak. The code fragment above may help you discover if you do
have a memory leak. Ditto Jsp's comment re trimming the working set. Both
are useful in development and debugging, but they have no place in production
code.


"Chris Mayers" wrote:

> OK,
>
> So should I override the Dispose method in Form2 and use it to call Dispose
> on each of its controls, I was thinking of giving that a shot anyway.
>
> Chris.
>
>
> "Phil Wilson" <pdjwilson@nospam.cox.net> wrote in message
> news:eFymFccQFHA.3704@TK2MSFTNGP12.phx.gbl...
> > If Form2 has a collection of controls on it, they've got Finalizers and
> > Dispose methods that aren't being called (because the only Dispose you're
> > calling is on Form2 itself). So it's possible that you have a queue of
> > Finalizers (for those controls) that haven't been called yet, and that
> queue
> > grows every time you instantiate a form2. The CLR Profiler should help you
> > see what's going on.
> >
> http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en
> > --
> > Phil Wilson
> > [Microsoft MVP-Windows Installer]
> >
> > "Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
> > news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
> > >
> > > I am trying to track a suspected memory leak in an application I'm
> writing
> > > and through repeated simplification of my project, I have found the
> > > following which is quite easily replicated should you be prepared to
> give
> > > me
> > > 5 minutes of your time...
> > >
> > > Create a new C# (Probably the same in VB dotNET but I've not tried it)
> > > Windows application with 2 forms, the default form -Form1 and one other
> > > one.
> > > that has a bunch of controls on it (say 20 buttons, 20 labels and a
> > > DataGrid) - Form2.
> > >
> > > On the default form, add a button to display the second form with some
> > > code
> > > like:
> > >
> > > private void button1_Click(object sender, System.EventArgs e)
> > > {
> > > using (form2 formTwo = new form2())
> > > {
> > > form2.ShowDialog();
> > > }
> > > }
> > >
> > > also on Form1 add a label, and a timer that updates the label text as
> > > follows (updates every 5 seconds -Interval = 5000-):
> > >
> > > private void timer1_Tick(object sender, System.EventArgs e)
> > > {
> > > label1.Text = GC.GetTotalMemory(False);
> > > }
> > >
> > > and finally a button that forces a Garbage Collection:
> > >
> > > private button2_Click(object sender, System.EventArgs e)
> > > {
> > > GC.Collect();
> > > }
> > >
> > > OK, my question/query is this, if I repeatedly click the button to open
> > > the
> > > second form, then close the second form, click the button, close the
> form
> > > etc. about 20-30 times, the display of GetTotalMemory seems to keep
> going
> > > up, and even after forcing Garbage Collections, never seems to get fully
> > > reclaimed. Should I care? and if I should, what (if anything) can I do
> > > about
> > > it?
> > >
> > > I would really appreciate an answer from someone who understands these
> > > things...
> > >
> > > Thanks a lot,
> > >
> > > Chris.
> > >
> > >
> > >
> > >
> >
> >
>
>
>

Re: GC, Should I care? by Jesse

Jesse
Sun Apr 17 01:35:55 CDT 2005

AMercer wrote:
> Re "So should I override ..", the answer is no, unless you are chasing a real
> memory leak. if you want to see memory reclaimed, then use
> GC.WaitForPendingFinalizers in cunjunction with GC.Collect. Once upon a
> time, while chasing a memory leak, I coded
>
> Dim i As Integer
> Dim l As Long
> For i = 1 To 3
> GC.Collect()
> GC.WaitForPendingFinalizers()
> l = GC.GetTotalMemory(True)
> Next
>

Yes, the correct way to force a garbage collection and ensure everything
that can be collected does indeed get collected is as follows:

Int64 totalMemory;

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

totalMemory = GC.GetTotalMemory();

The reason you must make two calls to GC.Collect is because the first
call queues inaccessible objects with finalizers in the finalization
queue--in other words, they're automatically promoted to the second
generation. This is why you always hear that you should avoid the use of
finalizers, and to make sure to explicitly and deterministically dispose
of such objects. Anyway, you then wait for the all of the objects to be
finalized, and then you perform a full collection again to collect the
now finalized objects.

Your loop implicitly does this; however, I'd make sure to retrieve the
total memory available after an additional call to GC.Collect, instead
of calling it immediately after GC.WaitForPendingFinalizers.

- Jesse Towner

Re: GC, Should I care? by Sean

Sean
Sun Apr 17 03:51:35 CDT 2005

"Jsp" <jsp@hotjktcom> wrote in message
news:ewvY6$bQFHA.924@TK2MSFTNGP14.phx.gbl...
> Use "SetProcessWorkingSetSize(-1,-1)" from kernel32.dll instead.

This does not clear up memory leaks. All it does is tell Windows to tidy up
the processes working set. This may result in less memory use for the
moment, but will significantly slow down your app when it needs to expand
it's working set (e.g. when it creates a new variable).

> "Chris Mayers" <chris_mayersBLUE@SUEDEYahoo.Com> wrote in message
> news:uy51RlbQFHA.3120@TK2MSFTNGP10.phx.gbl...
>>
>> I am trying to track a suspected memory leak in an application I'm
>> writing
>> and through repeated simplification of my project, I have found the
>> following which is quite easily replicated should you be prepared to give
>> me
>> 5 minutes of your time...
>>
>> Create a new C# (Probably the same in VB dotNET but I've not tried it)
>> Windows application with 2 forms, the default form -Form1 and one other
>> one.
>> that has a bunch of controls on it (say 20 buttons, 20 labels and a
>> DataGrid) - Form2.
>>
>> On the default form, add a button to display the second form with some
>> code
>> like:
>>
>> private void button1_Click(object sender, System.EventArgs e)
>> {
>> using (form2 formTwo = new form2())
>> {
>> form2.ShowDialog();
>> }
>> }
>>
>> also on Form1 add a label, and a timer that updates the label text as
>> follows (updates every 5 seconds -Interval = 5000-):
>>
>> private void timer1_Tick(object sender, System.EventArgs e)
>> {
>> label1.Text = GC.GetTotalMemory(False);
>> }
>>
>> and finally a button that forces a Garbage Collection:
>>
>> private button2_Click(object sender, System.EventArgs e)
>> {
>> GC.Collect();
>> }
>>
>> OK, my question/query is this, if I repeatedly click the button to open
>> the
>> second form, then close the second form, click the button, close the form
>> etc. about 20-30 times, the display of GetTotalMemory seems to keep going
>> up, and even after forcing Garbage Collections, never seems to get fully
>> reclaimed. Should I care? and if I should, what (if anything) can I do
>> about
>> it?
>>
>> I would really appreciate an answer from someone who understands these
>> things...
>>
>> Thanks a lot,
>>
>> Chris.
>>
>>
>>
>>
>
>
>
>



Re: GC, Should I care? by AMercer

AMercer
Sun Apr 17 05:10:02 CDT 2005

We are saying and doing the same thing. By coding GC.GetTotalMemory(True), I
am doing the 2nd GC.Collect() that you indicate. The for loop is used to
counter the following (related) info found in the remarks section of the
documentation for GC.GetTotalMemory(forceFullCollection):

"If forceFullCollection is true, this method waits a short interval before
returning while the system collects garbage and finalizes objects. The
duration of the interval is an internally specified limit determined by the
number of garbage collection cycles completed and the change in the amount of
memory recovered between cycles. The garbage collector does not guarantee
that all inaccessible memory is collected."

My objective was an accurate estimate managed memory to help chase a memory
leak. The phrases "short interval" and "does not guarantee" did not inspire
confidence, hence the for loop. In my environment, 3 iterations were
productive, and 4 or more were not.

"Jesse Towner" wrote:

> AMercer wrote:
> > Re "So should I override ..", the answer is no, unless you are chasing a real
> > memory leak. if you want to see memory reclaimed, then use
> > GC.WaitForPendingFinalizers in cunjunction with GC.Collect. Once upon a
> > time, while chasing a memory leak, I coded
> >
> > Dim i As Integer
> > Dim l As Long
> > For i = 1 To 3
> > GC.Collect()
> > GC.WaitForPendingFinalizers()
> > l = GC.GetTotalMemory(True)
> > Next
> >
>
> Yes, the correct way to force a garbage collection and ensure everything
> that can be collected does indeed get collected is as follows:
>
> Int64 totalMemory;
>
> GC.Collect();
> GC.WaitForPendingFinalizers();
> GC.Collect();
>
> totalMemory = GC.GetTotalMemory();
>
> The reason you must make two calls to GC.Collect is because the first
> call queues inaccessible objects with finalizers in the finalization
> queue--in other words, they're automatically promoted to the second
> generation. This is why you always hear that you should avoid the use of
> finalizers, and to make sure to explicitly and deterministically dispose
> of such objects. Anyway, you then wait for the all of the objects to be
> finalized, and then you perform a full collection again to collect the
> now finalized objects.
>
> Your loop implicitly does this; however, I'd make sure to retrieve the
> total memory available after an additional call to GC.Collect, instead
> of calling it immediately after GC.WaitForPendingFinalizers.
>
> - Jesse Towner
>