14 Replies - 2813 Views - Last Post: 24 February 2013 - 05:54 PM Rate Topic: -----

#1 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

How to free the unused occupied memory?

Posted 06 February 2013 - 12:05 PM

I had opened the task manager, watching how the memory usage of my program changes as I work with it - and it was only ever going up. I thought using Dispose() will free up the memory, but apparently it doesn't. Just a notice here, the dispose method I'm calling is of a custom made control made by someone else. Then I wrote GC.Collect(); after the code I close the form which won't be used anymore, but this had an insignifficant effect.
So how can I free up the unused memory? Thanks in advance.

Is This A Good Question/Topic? 0
  • +

Replies To: How to free the unused occupied memory?

#2 Ryano121  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1363
  • View blog
  • Posts: 3,002
  • Joined: 30-January 11

Re: How to free the unused occupied memory?

Posted 06 February 2013 - 12:11 PM

C# is a managed language meaning the the garbage collector takes care of freeing up unused resources. One of the main benefits is that you don't need to worry at all about .Dispose'ing of an object (unless its unmanaged like file streams etc).

The garbage collector will free the memory when it needs to. Unless your program is using up a load of system resources don't worry about it. The only thing you can really do is make sure you don't sustain any references to un-needed objects. If you still have a reference then the garbage collector won't free it. That being said still don't get caught up in it. Let the garbage collector do its job.
Was This Post Helpful? 2
  • +
  • -

#3 tlhIn`toq  Icon User is online

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5677
  • View blog
  • Posts: 12,211
  • Joined: 02-June 10

Re: How to free the unused occupied memory?

Posted 06 February 2013 - 12:15 PM

Ryan provided a really good explanation.

The long and sort of that means that your memory is going up because you are continuing to create objects that are remaining in scope (remaining alive).

So the fix for that is not GC - but fixing the logic of your program. I know that's not what you wanted to hear but that's how the cookie crumbles.
Was This Post Helpful? 4
  • +
  • -

#4 Curtis Rutland  Icon User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4577
  • View blog
  • Posts: 8,019
  • Joined: 08-June 10

Re: How to free the unused occupied memory?

Posted 06 February 2013 - 04:49 PM

Just adding my agreement. In a managed, garbage-collected language like C#, manual memory management really isn't a thing. If your memory is climbing over time (and it's not actually supposed to) that means that you have a memory leak in your logic, which you really can't fix by manually triggering Garbage Collection (which is generally a bad idea anyway; let the system maintain itself).

Read up on what IDisposable.Dispose actually does, as well as what GC.Collect does. You'll see that they don't fix memory issues in your program.

Now, as to finding the actual leaks in your program, I have no real experience. I'm sure there are some profilers that could help; I've never used them. I'd be interested in hearing other experts' advice about this as well.
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3664
  • View blog
  • Posts: 11,488
  • Joined: 05-May 12

Re: How to free the unused occupied memory?

Posted 06 February 2013 - 06:55 PM

I can't find the page right now, but this link has a subset of how to use memory better in managed applications:
http://msdn.microsof...chapt05_topic10

I wish I could find the other page because it had some nice illustrations of how memory is allocated and freed by different coding patterns. To me the illustrations spoke more to me about the impact of how I write my code as compared to the bulleted list in the link above.
Was This Post Helpful? 1
  • +
  • -

#6 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to free the unused occupied memory?

Posted 07 February 2013 - 05:38 AM

The long and sort of that means that your memory is going up because you are continuing to create objects that are remaining in scope (remaining alive).
Then when I don't need these objects anymore how to tell the garbage collector that they aren't being used anymore and are to be destroyed? I suspect not telling it might be the reason.
Here's the code I'm currently using:
public class Page
    {
        public DockContainer dock; public TabPage tab; public Form1 owner; public Shape oblik;
        public int ind; bool started;
//irrelevant code....
        public Page(Form1 f)
        {
            //some irrelevant code, namely initialziing variables

            dock = new Crom.Controls.Docking.DockContainer();
            //some lines of code setting the initial properties of dock

            tab = new System.Windows.Forms.TabPage();
            //some lines of code setting the initial properties of tab

            tab.Controls.Add(dock);
            owner.TabControl1.Controls.Add(tab);
        }

        public void Dispose()
        {
            oblik.Dispose(true, owner);
            dock.Dispose();
            tab.Dispose();
            GC.Collect();
        }
//more irrelevant code...
    }

//another class - owner is an instance of Page
// I call this when I want to close the tabpage
        private void closeButton_Click(object sender, EventArgs e)
        {
            owner.Dispose();
        }


Using this code upon pressing the close button the current TabPage is closed and this is due to tab.Dispose(); - when I remove tab.Dispose(); the tabpage is not closed, so I thought tab.Dispose(); is also calling destructors and stuff, which delete all the objects belonging to the tab page, but apparently it isn't. How do I do that? I suppose that the tabpage is still kept in the memory even though it's not shown in the tabcontrol anymore.

Should I finalize the variables or set them to null or both or what?
Was This Post Helpful? 0
  • +
  • -

#7 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3664
  • View blog
  • Posts: 11,488
  • Joined: 05-May 12

Re: How to free the unused occupied memory?

Posted 07 February 2013 - 06:28 AM

Ah, I found the page. I should have remembered that it was written by the great Jeffry Richter. (In my mind, Petzold is to Windows as Richter is to NT.)

http://msdn.microsof...e/bb985010.aspx

As I understand things, the point here is that the NextObjectPtr keeps moving up. (I'm not privy to the actual implementation, but I suspect it can be moved back down is some very special cases as optimization.) Conceptually, though, think of the NextObjectPtr keeps moving up until it hits the limit, and garbage collection happens. When that happens, the current segment is garbage collected, compacted, and promoted a generation. So that means that memory segment isn't freed up, but will be used later for other generations of objects that get promoted. A new segment is allocated to be used to satisfy the new set allocations. When the NextObjectPtr hits the end of the new segment another garbage collection happens again and objects are promoted again. Another segment is allocated again. The repeats until you have 3 generations: gen 0, gen 1, and gen 2.

More details here: http://msdn.microsof...he_managed_heap

So although you posted your code above, you still didn't fully disclose your calling pattern. When you say that memory usage keeps on going up, has your program already reached a steady state where you've been running and using it for awhile, and it still continues to eat memory?

I'm very leery about your way of closing a TabPage. Did you remove it first from the TabControl's Controls collection prior to disposing the TabPage? You have to recall that some of the WinForms controls that first appeared in .NET 1.1 are very thin wrappers around the Win32 controls and there is an implicit assumption that developers would continue to use them in the calling pattern as if some was writing a Win32 program rather than the newer style offered by WPF.

Also: You seem to be using a 3rd party control as the DockContainer. Are you sure it's not leaking (unmanaged) GDI resources?

In the end, we are all speculating here. Your best bet is to invest time (and possibly money) into getting a profiler that actually shows your memory usage patterns and you'll be better able to address your memory concerns, or lay your concerns to rest if things are working as designed.
Was This Post Helpful? 2
  • +
  • -

#8 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,500
  • Joined: 29-May 08

Re: How to free the unused occupied memory?

Posted 07 February 2013 - 12:58 PM

The GC won't free up memory if there any references to the object that is use that memory. For example forgetting to unhook Event handlers.
Was This Post Helpful? 1
  • +
  • -

#9 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: How to free the unused occupied memory?

Posted 08 February 2013 - 02:20 PM

View Posttriangulator, on 07 February 2013 - 08:38 AM, said:

The long and sort of that means that your memory is going up because you are continuing to create objects that are remaining in scope (remaining alive).
Then when I don't need these objects anymore how to tell the garbage collector that they aren't being used anymore and are to be destroyed? I suspect not telling it might be the reason.


Using this code upon pressing the close button the current TabPage is closed and this is due to tab.Dispose(); - when I remove tab.Dispose(); the tabpage is not closed, so I thought tab.Dispose(); is also calling destructors and stuff, which delete all the objects belonging to the tab page, but apparently it isn't. How do I do that? I suppose that the tabpage is still kept in the memory even though it's not shown in the tabcontrol anymore.

Should I finalize the variables or set them to null or both or what?


You don't need to manually tell the GC to collect. You can, but it's frowned upon. The GC will collect when it gets ready to. There is no schedule. If you are removing all references and handling everything correctly in your Dispose, then the objects are getting disposed of correctly. However, the memory won't be reclaimed until the GC collects. That could be 2 minutes from the time you call Dispose, or 2 hours, or longer.

Don't worry about the size of the memory your application is using until you notice a problem like an OutOfMemoryException is thrown. Your app will consume a lot of memory. That memory will be reclaimed eventually if you are killing all of the references correctly.

As Adam states, one of the main "memory leaks" that occurs in .Net is when we do not unsubscribe from events. Anytime you manually do a "+=" to subscribe, you also need to unsubscribe("-="). Without the unsubscription, the object will remain in memory as it will still have a reference for the event handler.
Was This Post Helpful? 1
  • +
  • -

#10 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to free the unused occupied memory?

Posted 10 February 2013 - 01:42 AM

And if I don't need an object, which I have initialized with the new statement, anymore should I set it to null?
void dosomething(ref Point a, ref Point B)/>
{
Point temp = new Point();
//does some geometric calculations with the three points;

a.X = temp.X;
b.Y = temp.Y;//now I don't need temp anymore

temp = null;//my question is - is this line even necessary?
}


As far as I understood, it is necessary since it tells the GC to destroy temp and/or to free the memory it is using, otherwise it remains until the program ends. Is this so?
Was This Post Helpful? 0
  • +
  • -

#11 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 992
  • View blog
  • Posts: 972
  • Joined: 30-September 10

Re: How to free the unused occupied memory?

Posted 10 February 2013 - 02:24 AM

EDIT: I've just recognized that the object in question is of type Point. This is a struct, not a class, so you cannot set temp to null (the compiler won't let you), as things stand. Also, it is a struct allocated locally in the method, so in the current implementations of the CLR's JIT compiler, I believe the point will be allocated on the stack, or in CPU registers. As the garbage collector deals with the managed heap, it plays no part in the cleaning up of the Point object here :).

So, assuming temp does reference an object allocated on the managed heap...

No, setting temp to null is not necessary. As soon as dosomething() returns, the object that was referenced by temp will become unreachable anyway, and so will be automatically eligible for garbage collection. Further, you must remember that setting a field to null won't cause the garbage collector to run.

One case you may hear for setting a instance field to null (often in a Dispose() method) is when that field references a very large object. What that will do is ensure that the large object can be garbage collected promptly (if necessary), even if the containing object is still referenced by the calling code. The argument is that that may help to significantly reduce memory pressure, due to the size of the object.

I think that's really defensive though, and if you've called Dispose() on the containing object, should it really still be in scope in your code? Setting large object fields to null may be a reasonable precaution in a public API that is going to be used by many developers, in many different ways, but in well written code that is not going to be used publicly, it's probably of little value, in my opinion.

So, I would say there is usually, in a well written application, absolutely no need to set references to null just for the sake of the garbage collector. Besides, I personally think it is a good idea to aim to avoid nulls in production code all together.

In summary, scope objects sensibly (for example, don't have a load of unnecessary static variables), and the garbage collector will do its job well; freeing you from any memory related worries. As tlhIn`toq suggested, if you find yourself having to set variables to null to allow memory to be reclaimed, you have a problem in the way your application is structured.

This post has been edited by CodingSup3rnatur@l-360: 10 February 2013 - 06:12 AM
Reason for edit:: Note about Point being a struct, not a class.

Was This Post Helpful? 1
  • +
  • -

#12 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 992
  • View blog
  • Posts: 972
  • Joined: 30-September 10

Re: How to free the unused occupied memory?

Posted 10 February 2013 - 02:48 AM

Quote

is also calling destructors and stuff, which delete all the objects belonging to the tab page


Destructors (or, more precisely, finalizers), and Dispose() are NOT in the business of freeing managed memory. They are used for freeing resources that the garbage collector cannot clean up, like file handles, db connections etc.

Remember that finalizers simply define pieces of code that run before an object is finally garbage collected, in order to clean up unmanaged resources. If an object that defines a finalizer is never made eligible for garbage collection, then the finalizer will never run.

I don't know if you have a C++ background (the evidence suggests you may have), but C++ destructors are very different to C# finalizers. Don't let the similar syntax fool you :).


Code like this may cause problems:

owner.TabControl1.Controls.Add(tab);



If owner remains reachable after the tab page is closed, the tab page won't be eligible for garbage collection because the tab control's Controls collection still holds a reference to the tab page. Maybe try removing the tab pages from the Controls collection, as well as disposing of them?

I believe the call to Dispose() on the tab page should indirectly remove it from the Controls collection, but that is assuming you actually call Dispose() on all the Page instances you create...

If that is causing a problem, the problem with likely transitively apply to this code too - tab.Controls.Add(dock);, meaning each DockContainer you create will not become eligible for garbage collection.

Our new junior developer at work made that mistake, where they were constantly adding controls to the Controls collection, without ever removing them, and consequently getting out of memory exceptions days after starting the application up.


EDIT: I've just noticed you are actually calling owner.Dispose(), and that Skydiver already made the above point. My apologies, guess I haven't fully woken up yet... Anyway, assuming owner.Dispose() is always called when the page is closed, that should mean all controls on the Form1 instance are removed from their Controls collections (as I believe Dispose() does this for you), meaning the above probably doesn't apply in this case.


Just a side note, accessing a form's UI control directly from the outside like that is bad practice. The form itself is the only one who should be able to add or remove controls directly like that.

This post has been edited by CodingSup3rnatur@l-360: 10 February 2013 - 06:38 AM

Was This Post Helpful? 1
  • +
  • -

#13 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6110
  • View blog
  • Posts: 23,670
  • Joined: 23-August 08

Re: How to free the unused occupied memory?

Posted 10 February 2013 - 06:32 AM

SciTech Software's .NET Memory Profiler is an excellent product for tracking down these issues. Haven't needed to use it in a long time, but it did the job well for me when I did need it.
Was This Post Helpful? 0
  • +
  • -

#14 triangulator  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 27
  • Joined: 03-February 13

Re: How to free the unused occupied memory?

Posted 24 February 2013 - 12:42 PM

Now that I used the Memory Profiler, I saw that all instances that the program ever created remain to exist, no matter they are never shown anymore and that I have removed the controls from the corresponding containers.
Here is the code I have currently:
public class Page
    {
public DockContainer dock; public TabPage tab; public Form1 owner; public Shape myshape;
        public int ind; bool started,dispozd=false;
        System.EventHandler<Crom.Controls.Docking.FormEventArgs> bzbg;
        System.EventHandler bzbgtab;

public Page(Form1 f, string _ss, int kk)
        {
            started = true;
            //.....
            bzbg = new System.EventHandler<Crom.Controls.Docking.FormEventArgs>(this.dockContainer1_FormClosed);
            dock.FormClosed += bzbg;
            //....
            bzbgtab = new System.EventHandler(this.initialize); 
            tab.Enter += bzbgtab;
         //  ....
            tab.Controls.Add(dock);

            owner.shapes.Controls.Add(tab);
                  //....
        }
public void Dispose()
        {
            if (!dispozd)
            {

                dispozd = true;
            owner.broi--;
            owner.shapes.Controls.Remove(tab);
            dock.FormClosed -= bzbg;
            tab.Enter -= bzbgtab;
            tab.Controls.Remove(dock);
            MessageBox.Show("im being disposed "+tab.Text);
            myshape.Dispose(true, owner);
            dock.Clear();
            dock.Dispose(); dock.Hide();
            tab.Controls.Clear();
            tab.Dispose(); tab.Hide();
             dock = null; tab = null; myshape = null;
        }
            
            
        }
//...



I get all the messages, remove the controls from the containers, remove the references, dispose all childs and yet all controls - including the instances of class Page above and the tab pages - remain, although not in the tabcontrol. Now I'm probably going to ask a stupid question, but how do I delete those objects? There is no function such as .Close() or .Delete() or .End() or .Stop() or whatever. I am certainly missing something big here.
Also, I don't do anything with the GC manually anymore.
Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3664
  • View blog
  • Posts: 11,488
  • Joined: 05-May 12

Re: How to free the unused occupied memory?

Posted 24 February 2013 - 05:54 PM

If Memory Profiler is worth its salt, it should not only tell you which objects are still alive, but more importantly, which parent objects are keeping them alive. What does it tell you about who or what is retaining the reference.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1