locked
Innate memory leak with C#? RRS feed

  • Question

  • Hi,

        I've been doing some testing with C#, and it seems that innate to the language is a memory leak, or so it seems.  If you create a completely blank form, and run it, when you move the mouse over the form, memory usage slowly increases until it finally peeks out at about 700k.  As you I add more and more buttons, labels, and other things, this number slowly increases.  Right now my applications memory usage slowly increases until it peeks out at 1200k.  In order to see this increase, you do have to continually move the mouse over the form.

    Has anyone heard of this before? What is the cause and is there a way around it?

    Here is sample code I used to create the blank form:

    using System.Windows.Forms;
    namespace ActiveXTest
    {
        public class Form1 : System.Windows.Forms.Form
        {
            static void Main()
            {
                Application.Run(new Form1());
            }
        }
    }
    Monday, September 11, 2006 10:48 PM

Answers

  • It's funny, as almost all programmers that begin(?) working with .NET are conserned with this issue. Trust me, there are thousands and thousands .NET programs manufactured and sold every year, and surely someone has noticed if the framework would leak memory with its basic functionalities. .NET loads assemblies and compiles types and methods at runtime to memory, these will raise the memory a bit, but these are shared with all running .NET programs.

    Ok, do a simple test. Create new windows project, and add a timer component on it. Enable it,  set interval to 1000, and create tick event handler where you make a following call:

    GC.Collect(GC.MaxGeneration); //This will fire up the full garbage collection

    Now compile in release mode, run it from exe and inspect the memory rise. No memory rise there with mouse movement, since garbage collection is performed on every second.

    Note, that you should not use this in a real life application, since it is just a excess burden to the program. Garbage collector WILL take actions necessary to keep the memory cleaned.
    Thursday, September 14, 2006 6:30 AM
  • Good idea with GC.Collect and the timer rauhanlinnake . I have just a little addition to your entry. The memory allocated for loaded assemblie/classes/methods and the memory allocated for jit compiling is not shared. The only way the jit compiled code is shared is when you ngen an assembly. It's true that most of the framewors assemblies (including System.Windows.Forms) are ngened so if you see memory increasing for just an empty form then almost for sure the cause is the garbage collector.
    Thursday, September 14, 2006 7:41 AM

All replies

  • You have a memory leak when the memory usage increases with no limit while the application is running. Since you states yourself that "it peeks at 1200k" then it's not a memory leak, that's normal memory usage for a .NET application.

     

    Monday, September 11, 2006 10:52 PM
  • OK, so I clearly understand, you are saying that memory leaks are only memory leaks if they do not have a peak and that watching the memory climb while you move your mouse around is perfectly normal in the .NET world?
    Tuesday, September 12, 2006 9:50 PM
  • Memory leaks don't necesarilly have a peak. You can allocate something in the begging of the process and not freeing it ever. Obviously you won't see memory increasing because the action does not repeat.

    But this case was about a action that repeats (mouse move) and memory usage that increases and then stops. If there was a memory leak then the memory usage would have increase without limit.

    In addtion you really can't leak memory in .NET because of the garbage collector. You can leak managed resource but since you are saying that it's just a simple form with some buttons and labels on it then you probably have nothing like this in there.

     

    Tuesday, September 12, 2006 10:56 PM
  • "I've been doing some testing with C#, and it seems that innate to the language is a memory leak, or so it seems. If you create a completely blank form, and run it, when you move the mouse over the form, memory usage slowly increases until it finally peeks out at about 700k. ....."

    You have been using Windows Task Manager to determine the memory consumption of the .NET program? The task manager DOES NOT show the memory consumption of the single .NET program correctly. Task manager shows also the .NET shared memory along the your program process memory consumption. You get quite close with your programs memory consumption, when you minimize your program. To get the real memory figures for you must use the Performance Monitor.

    There has been a tutorial for that, but i can't find it right now... I try to find it.
    Wednesday, September 13, 2006 7:18 AM
  • OK - so let's get off the tangent of memory leak definition as we apparently disagree.

    Ultimately, the report here is that the mouse movement causes memory to climb.

    If this is expected memory in .NET, that is where the question seems to lie. If it is not, he is looking for a resolution. IMHO, this is not normal behavior (nor should it be) of any application.

    Wednesday, September 13, 2006 4:58 PM
  • First, a memory leak happens when you allocate some memory and then you lose the pointer to it so you have no way to free it. Some people may add that simply not freeing something at the right time is also a memory leak. Fine.

    Now how do you track a memory leak ? Well, certainly not with Task Manager or any other tool that simply indicates memory usage from the OS point of view. What you can see in Task Manager is one possible side-effect of the memory leaks, increasing memory usage. Now since the memory usage stops increasing at some point while repeating the same action then the chance that what you are seeing is the side-effect of a memory leak is very very low. In .NET, or other language/runtime/platform. So, "the report here is that the mouse movement causes memory to climb" and also to stop at some point.

    So why does memory usage increases while mouse moves ?

    Couple of possible reasons:

    1. each control on the form does some sort of "lazy" allocation. It allocates something when the mouses enters the component for the first time and this something is not released until the form is closed (BTW, what happens when the form is closed was not mentioned altough it's quite important)

    2. the .NET runtime needs to load information about some assemblies/classes/methods that are invoked as a result of the mouse movement (some event handlers perhaps) and  maybe it also needs to jit compile them. This things require memory to be allocated and this memory is not freed until the process ends.

    3. .NET objects are not freed when they are not needed but when the garbage collector decides that memory is needed.

    So I'd say that this is normal behavior and not an "innate memory leak with c#".

    Of course, I could be wrong but given the current information I doubt it. We don't even know what controls are on the form, the code sample presented show how the Form1 is displayed, but doesn't show how Form1 actually looks like...

     

    Wednesday, September 13, 2006 6:39 PM
  •  rauhanlinnake wrote:
    You have been using Windows Task Manager to determine the memory consumption of the .NET program? The task manager DOES NOT show the memory consumption of the single .NET program correctly. Task manager shows also the .NET shared memory along the your program process memory consumption. You get quite close with your programs memory consumption, when you minimize your program. To get the real memory figures for you must use the Performance Monitor.

    There has been a tutorial for that, but i can't find it right now... I try to find it.

     

    I agree this might be a good resolution for tracking the issue, but even if this is a shared memory issue, does it not throw a flag up to anyone as being a problem? Moving a mouse and watching memory rise (even shared)?

    Wednesday, September 13, 2006 8:09 PM
  • Well, rather than guessing, I built and ran some test apps. Note, the most important thing to note is that I did nothing but create the app with the project wizard (VS2003), hit build (although I tested in release as well) and then hit run. In all cases of .NET (C#, VB.NET and a .NET app in CPP) the mouse move event generated a memory climb. O nthe other hand, an unmanaged C++ app did not. So, I do believe this is a .NET issue. However, your summation of 'lazy' allocation (when the form is closed the app exits so no more memory tracking can be done because it is all released unless using a system wide memory utility which I did not do for this test) scares the heck out of me if it truly is mouse movement based. BTW, this is with NO controls on the form.
    Wednesday, September 13, 2006 11:58 PM
  • It's funny, as almost all programmers that begin(?) working with .NET are conserned with this issue. Trust me, there are thousands and thousands .NET programs manufactured and sold every year, and surely someone has noticed if the framework would leak memory with its basic functionalities. .NET loads assemblies and compiles types and methods at runtime to memory, these will raise the memory a bit, but these are shared with all running .NET programs.

    Ok, do a simple test. Create new windows project, and add a timer component on it. Enable it,  set interval to 1000, and create tick event handler where you make a following call:

    GC.Collect(GC.MaxGeneration); //This will fire up the full garbage collection

    Now compile in release mode, run it from exe and inspect the memory rise. No memory rise there with mouse movement, since garbage collection is performed on every second.

    Note, that you should not use this in a real life application, since it is just a excess burden to the program. Garbage collector WILL take actions necessary to keep the memory cleaned.
    Thursday, September 14, 2006 6:30 AM
  • Good idea with GC.Collect and the timer rauhanlinnake . I have just a little addition to your entry. The memory allocated for loaded assemblie/classes/methods and the memory allocated for jit compiling is not shared. The only way the jit compiled code is shared is when you ngen an assembly. It's true that most of the framewors assemblies (including System.Windows.Forms) are ngened so if you see memory increasing for just an empty form then almost for sure the cause is the garbage collector.
    Thursday, September 14, 2006 7:41 AM
  • Thanks guys.  You were all great help.
    Thursday, September 14, 2006 5:19 PM