Serious Memory Leaks Plague WPF
WPF, also known as Windows Presentation Foundation, represents the future of UI on the Windows platform. And if Microsoft has its way, its younger sibling Silerlight will take over the web and mobile markets. But like any new technology, it has some issues to work through including some rather serious memory leaks.
There are many memory leaks to discuss, so bare with us. The first one has been known for a while, but its cause is non-obvious to most developers, even ones reasonably familiar with WPF. The conditions needed to cause it follow:
- A data-binding path refers to property P of object X.
- Object X contains a direct reference or an indirect reference to the target of the data-binding operation.
- Property P is accessed through a PropertyDescriptor object instead of a DependencyProperty object or a PropertyInfo object.
This issue is described in detail in KB 938416.
Next up is a nasty bug that is triggered when you replace one data-bound collection with another. Ayende Rahien has a block of code that reproduces the issue. For an explanation, we turn to Mike Brown:
Digging in I discovered that the Binding System doesn't deregister the listener for the "Name" property when you notify that Data has changed.
It's definitely a bug and it has to do with the way the binding system looks at the binding in question. When you notify that Data has changed, rather than deregistering the existing bindings further down the tree (in this case the Name binding on your Textblock) and reusing the elements it appears that an entirely new set of elements are created. Unfortunately, the Textblock never gets the opportunity to deregister its binding.
Now if you made Data an observable collection (necessitates making your anonymous type into a full class) and made the collection raise a CollectionChanged event (e.g. Data=Data), everything works just fine.
This next group of memory leaks come to us from a Microsoft blogger going by the handle jgoldb.
- CMilChannel leaks if initial HWND is destroyed on XP.
- ShutdownListener leaked for each thread using Binding
- Create and Destroy WriteableBitmap on XP in HW
- SW Viewport 3D w/ VisualBrush, WB, etc. leaks on XP
In addition to these leaks, he lists some other common developer mistakes that lead to memory leaks as well as some past WPF issues that have been since corrected.
Memory leak or memory leak?
To an 'old school' dev, a memory leak usually means memory that's still allocated after program execution completes and not released back to the OS.
To a Java/.Net developer, we usually mean something that is 'mysteriously' not being garbage collected.
Usually, in a GC'ed language, failure to collect is traceable to the developer in the long run. However, it requires the dev understanding nuances to anticipate the problem. Examples include events and handles to unmanaged resources in the .net world. At any rate, this kind of leak usually goes away with application shut down. Quite unlike an old school lead, that is.
Re: Memory leak or memory leak?
I guess there might be some chance for a resource leak, where in some funky situation a program acquires a resource, then dies but doesn't manage to return it (and the resource is not one that automatically gets released after the demise of the process). But I wouldn't quite call these memory leaks.
If there's a memory leak in a non-GC environment, it's simply a case of a malloc (or one of its pals) that's not matched by a free.
In GC environments I find memory leaks are usually not caused by bad book keeping of memory blocks but by conceptual errors at a higher level; eg. adding listeners to models or GUI elements but not removing them, which is bad if the model or GUI lives longer than the developer expected.
Brandon Holt, Preston Briggs, Luis Ceze, Mark Oskin May 21, 2015