Memory Leak in C#

2019-01-04 06:35发布

Is it ever possible in a managed system to leak memory when you make sure that all handles, things that implement IDispose are disposed?

Would there be cases where some variables are left out?

20条回答
别忘想泡老子
3楼-- · 2019-01-04 06:52

It's a myth that you cannot leak memory in managed code. Granted, it's much harder than in unmanaged C++, but there are a million ways to do it. Static objects holding references, unnecessary references, caching, etc. If you are doing things the "right" way, many of your objects will not get garbage collected until much later than necessary, which is sort of a memory leak too in my opinion, in a practical and not theoretical way.

Fortunately, there are tools that can assist you. I use Microsoft's CLR Profiler a lot - it is not the most user friendly tool ever written but it is definitely very useful and it is free.

查看更多
在下西门庆
4楼-- · 2019-01-04 06:53

As others have pointed out, as long as there's not an actual bug in the memory manager, classes that don't use unmanaged resources won't leak memory.

What you see in .NET is not memory leaks, but objects that never get disposed. An object won't get disposed as long as the garbage collector can find it on the object graph. So if any living object anywhere has a reference to the object, it won't get disposed.

Event registration is a good way to make this happen. If an object registers for an event, whatever it registered with has a reference to it, and even if you eliminate every other reference to the object, until it unregisters (or the object it registered with becomes unreachable) it will stay alive.

So you have to watch out for objects that register for static events without your knowledge. A nifty feature of the ToolStrip, for instance, is that if you change your display theme, it will automatically redisplay in the new theme. It accomplishes this nifty feature by registering for the static SystemEvents.UserPreferenceChanged event. When you change your Windows theme, the event gets raised, and all of the ToolStrip objects that are listening to the event get notified that there's a new theme.

Okay, so suppose you decide to throw away a ToolStrip on your form:

private void DiscardMyToolstrip()
{
    Controls.Remove("MyToolStrip");
}

You now have a ToolStrip that will never die. Even though it isn't on your form anymore, every time the user changes themes Windows will dutifully tell the otherwise-nonexistent ToolStrip about it. Every time the garbage collector runs, it thinks "I can't throw that object away, the UserPreferenceChanged event is using it."

That's not a memory leak. But it might as well be.

Things like this make a memory profiler invaluable. Run a memory profiler, and you'll say "that's odd, there seem to be ten thousand ToolStrip objects on the heap, even though there's only one on my form. How did this happen?"

Oh, and in case you're wondering why some people think property setters are evil: to get a ToolStrip to unregister from the UserPreferenceChanged event, set its Visible property to false.

查看更多
走好不送
5楼-- · 2019-01-04 06:53

Small functions help in avoiding "memory leaks". Because garbage collector frees local variables at the end of functions. If function is big and takes a lot of memory you yourself have to free local variables that take a lot of memory and are no longer needed. Similary global variables (arrays, lists) are also bad.

I experienced memory leaks in C# when creating images and not disposing them. Which is a little strange. People say you have to call .Dispose() on every object that has it. But documentation for graphical C# functions doesn't always mention this, for example for function GetThumbnailImage(). C# compiler should warn you about this I think.

查看更多
ゆ 、 Hurt°
6楼-- · 2019-01-04 06:56

As already mentioned the keeping references around will lead to increasing memory usage over time. An easy way to get into this situation is with events. If you had a long living object with some event that your other objects listen to, if the listeners are never removed then the event on the long lived object will keep those other instances alive long after they are no longer needed.

查看更多
beautiful°
7楼-- · 2019-01-04 06:58

It's possible to have leaks if unmanaged resources do not get cleaned properly. Classes which implement IDisposable can leak.

However, regular object references do not require explicit memory management the way lower level languages do.

查看更多
登录 后发表回答