0

I'm making a C# application currently in WinForms, and am facing memory leak issues.

When the user clicks a button, a method is called, where new variables are being created. They can catch 50M-100M in RAM (sometimes it's file handling, but it happens with every other type of variable as well).

Now, the problem is, after the method is completed, the memory still remains at 50M-100M, and it appears as if they're (the variables) not being destroyed (I watch the memory being used with Task Manager).

If I created them inside a method, shouldn't the GC destroy them when the method ends? And if it does destroy them, why do it still shows high memory usage?

Or maybe is it related to the fact that the method is being called by a button click event? I also run the program in the VS debugger, if that matters.

So, what should I do to avoid this? The variables are 100% not global so it's not this type of problem.

Travier
  • 205
  • 2
  • 9
  • 1
    Running it in the debugger matters a lot. Many many things are done differently if you are debugging, especially about when objects are garbage collected. Also this could potentially be a duplicate of http://stackoverflow.com/questions/823661/explicitly-freeing-memory-in-c-sharp – Scott Chamberlain Mar 23 '14 at 21:55

3 Answers3

3

If I created them inside a method, shouldn't the GC destroy them when the method ends?

No. At that point the objects might be eligible for garbage collection, but collection is not triggered by exiting the method. GC is triggered when allocations require it or when the system is low on memory.

Another issue here is that Task Manager reports process memory. The .NET runtime allocates and frees memory on behalf of the managed application and it tries to be smart about how this is done. Consequently, the runtime will typically not free segments as soon as they are no longer needed to support the managed heap. The effect of this is that your application can reduce its managed memory usage without this being immediately reflected in process memory.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • You are right, they weren't destroyed when the method ended. Using GC.Collect(), as Kasper suggested, has solved the problem. Thanks anyway! (I can't upvote you yet because I don't have the required reputation). – Travier Mar 23 '14 at 22:04
  • @Travier The question is, was it really a problem. The CLR will get around to doing it's own colloection when it detects that it needs one, by forcing one early you are just deceasing the performance for what gain? Remember "Free memory is wasted memory" you *want* your programs to use all the memory they can. – Scott Chamberlain Mar 23 '14 at 22:10
0

The first thing you should check is whether you are working with any objects that implement IDisposable. If this is the case then ensure these are disposed before leaving their scope.

Another thing you should try is to call GC.Collect and see if that removes the objects from memory. If this is the case then you do not have memory leak, garbage collection was just waiting a bit before removing your objects.

If none of these fix your issues then you must still have a reference to the objects created inside your methods. Do you create some objects that continue to exist after the method ends which might have references to the objects you thought would be GC'ed?

Kasper Holdum
  • 12,993
  • 6
  • 45
  • 74
0

It's not necessarily true that they will be garbage-collected right after ending a method. The normal behavior of .NET garbage collector is that it's not deterministic, that is, it won't run on a precisely determined time, so you can never be sure when the memory is going to be released.

After finishing a method, all variables go out of scope, and assuming that, as you said, no more global references are kept to those objects, they are not eligible for being collected, but it don't means that they will be immediately. GC will run on the background, normally on idle times, but again, we can never be sure when it will reclaim the memory. It's totally normal to see this behavior.

If memory issues are really pressing, you may try to force an immediate garbage collection by calling GC.Collect method.

Alejandro
  • 7,290
  • 4
  • 34
  • 59