I have been searching for a tool to debug unreleased COM references, that usually cause e.g. Word/Outlook processes to hang in memory in case the code does not call Marshal.ReleaseCOMObject on all COM instances correctly. (Outlook 2007 partially fixes this for outlook addins, but this is a generic question).
Is there a tool that would display at least a list of COM references (by type) held by managed code? Ideally, it would also display memory profiler-style object trees helping to debug where the reference increment occured.
Debugging at runtime is not that important as being able to attach to a hung process - because the problem typically occurs when the code is done with the COM interface and someone forgot to release something - the application (e.g. winword) hangs in memory even after the calling managed application quits.
If such tool does not exist, what is the (technical?) reason? It would be very useful for debugging a lot of otherwise very hard to find problems when working with COM interop.
Not quite the answer (or as simple as) you are looking for, but ReleaseCOMObject (as does the native Release which it wraps) returns an Integer which should indicate the number of outstanding references remaining. You could add code to your project to explicitly do an AddRef so you could then Release, and see the new count, and see if it is what you are expecting, etc.
Here is my answer to debugging COM references using debugger
Troubleshooting a COM+ application deadlock
Related
I have an application which does a bunch of text parsing. After each pass it spits out some info into a database and clears out all the internal state.
My issue is the memeory allocated in Windows Task Mgr / Resource Monitor keeps growing and growing. I've done some profile using .Net Mem Profiler and it looks like it should be going down. Here is a screen shot from the profiler:
But in the Task Mgr after each pass the memory private working set increases. I'd like for the memory to grow as its used and then return to a normal level after each pass, that way I could keep this thing running.
Any advice on what to look for or any ideas what causes this?
A few things to check for are:
Event handlers keeping objects alive, make sure that if the object which subscribes to an event goes out of scope before the object publishing the event that it unsubscribes from the event to prevent the publishing object keep a reference to it.
Make sure that you call dispose on any object which implements IDisposable. Generally speaking objects which implement IDisposable contains resources which need special tidy up.
If you reference any com objects, make sure you release them properly.
You shouldn't ever have to call GC.Collect() within production code.
Task Mgr is not an accurate representation of the memory your application is actually using. Its more a representation of how much memory windows has allotted or planned for your application- if you app needs more, windows can expand this number, but if your app needs less, windows may not re-allocate this memory until another application actually needs it..
I think what you have above is a pretty accurate representation of what your application is actually doing (ie, its not leaking).
This forces .NET to collect all unused objects from memory, therefore reclaiming some of it:
GC.Collect();
GC.WaitForPendingFinalizers();
If you do have a memory leak, you can use the SOS debugging extension to try to find it. This article is also a very good example and a little more complete then what my answer will include.
You can use this in either VS or WinDbg, and the only difference is how you load the dll. For Visual Studio, first enable unmanaged debugging in the debug tab of your project's properties. When it comes time to load it, use .load SOS.dll in the Immediate Window. For WinDbg, either open the executable or attach to the process, and, to load it, use .loadby sos clr for .NET 4 or .loadby sos mscorwks for 2 or 3.5.
After letting the application run for a while, pause it (break all). Now you can load SOS. Upon success, enter !dumpheap -stat. This will list off how much memory each class is using. If this isn't enough to find the leak, the other article I linked goes into more depth on how to locate the memory leak.
One way to solve this is break up your work into separate executable programs. Once a program completes its work and ends, all its memory will be reclaimed by the system.
I am writing an editor in C#/.NET using AvalonDock.
If i close a document, the memory-consumption of my program doesn't decrease. Even if I call the garbage collector manually. So i assume that there is still a reference of the document somewhere.
The software is huge and the document is a very central component, so it's not easy to find every reference to it.
Does the Visual Studio 2010 debugger have a functionality to search for objects of a certain class in memory or something?
Alternatively, what would you do, if faced with such a problem?
You need to use a memory profiler to find out what objects are in memory and what holds a reference to them.
There are several different options - commercial and free.
You can do what you want using free tools.
The basic steps are as follows:
Run Your Application
Attach windbg to its process
Load the "sos" helper module (.loadby sos mscorwks)
Dump the heap (!DumpHeap -stat)
Find the type you're interested in and see if it's actually the thing using memory
Dump the heap for your particular type (!DumpHeap -type MyNameSpace.MyType)
Find the memory address of an object you think should be disposed, and see if it is "rooted" somewhere. (!gcroot "whatever the address was")
I've personally used this technique to great effect when tracking down memory leaks in graphics-intensive c# programs.
I learned this from Rico Mariani of Microsoft. Here is a blog entry that describes it in detail.
* http://blogs.msdn.com/b/ricom/archive/2004/12/10/279612.aspx
Remember that even when .net cleans itself up, windows may not decide to actually release the memory. Often it only does so when another application actually needs memory. So, use a memory profiler :)
I've got a p-invoke call to an unmanaged DLL that was failing in my WPF app but not in a simple, starter WPF app. I tried to figure out what the problem was but eventually came to the conclusion that if I assign too much memory before making the call, the call fails. I had two separate blocks of code, both of which would succeed on their own, but that would cause failure if both were run. (They had nothing to do with what the p-invoke call is trying to do).
What kind of issues in the unmanaged library would cause such an issue? I thought that the managed and unmanaged heaps were supposed to be automatically separated.
The crash as far as I can tell is happening in a dynamically loaded secondary DLL from the one p-invoked into. Could that have something to do with it?
Unmanaged code is prone to corrupt the heap. The side effects of that corruption are very unpredictable, it depends on what happens afterwards with that corrupted memory. It is not uncommon that nothing bad happens if the corruption is not in a crucial location. Changing the memory allocation pattern of your program can change that outcome.
All you really know right now is that the unmanaged code can't be trusted. Doing something about it is invariably hard, especially from a managed host program. You won't get anywhere until you start writing unit tests for that unmanaged code, using unmanaged code to exercise it, and find a reproducible bomb that you could tackle with an unmanaged debugger.
A shot in the dark given there is not much info to work with.
Is it possible that the unmanaged DLL needs to be loaded at a specific base address and when you allocate too much memory or other assemblies are loaded, the DLL is not able to load at the correct address.
http://msdn.microsoft.com/en-us/library/w368ysh2.aspx
Is there a way to find out the memory usage of each dll within a c# application using com dll's? Or what would you say is the best way to find out why memory grows exponentially when using a com object (IE. Whether the COM object has a memory leak, or whether some special freeing up of objects passed to managed code has to occur(and/or how to do that)).
Are you releasing the COM object after usage(Marshal.ReleaseComObject)?
What type of parameters are you passing in/out of the calls?
If you don't have the COM object source code and want to determine why its 'leaking', Run the COM object outa proc, attach WinDBG to the process and set breakpoints on memory allocation APIs(HeapAlloc,etc...). Look at the call stack and allocation patterns. Sure you can use profilers on the managed side but if you want to know what is going on you are going to have to get your hands dirty...
A Microsoft support engineer has a fabulous blog that walks through lots of cases like this. She goes over all the tools she uses. I found it extremely helpful to read through all of her posts when I was debugging this kind of stuff a few years ago.
Edit: Apparently, she has added a series of labs that explain how to setup your environment and diagnose different problems. You may want to start here.
dotTrace rocks: http://www.jetbrains.com/profiler/
Keep in mind that all COM objects in .NET are basically MarshalByRefObject-derived classes at heart, so you should be able to look for memory consumption by such objects as one potential filter.
First thing I'd want to do is be absolutely certain that I'm not leaking references anywhere, then go into the smallest steps that will reproduce the steps (a good profiler is essential, I happen to use and recommend RedGate's ANTS Profiler) -- it can be done, and it is worth sending example code that reproduces the issue to the vendor of the COM object so they can resolve it (There is actually a hotfix for Crystal Reports as a result of a memory leak in it which I found :)
Is it really necessary to release COM components from Office PIA, when you don't need them anymore by invoking Marshal.ReleaseComObject(..)?
I found various and contradictory advices on this topic on the web. In my opinion, since Outlook PIA is always returning a new references to its interfaces as returning values from its methods, it is not necessary to explicitly release it. Am I right?
For VS 2010, see Marshal.ReleaseComObject Is Considered Dangerous.
With Microsoft Office, in general, you do need to explicitly release your references, which can be safely done in two stages:
(1) First release all the minor object to which you do not hold a named object variable via a call to GC.Collect() and then GC.WaitForPendingFinalizers(). (You need to call this twice, if the objects involved could have finalizers, such as when using Visual Studio Tools for Office (VSTO).)
(2) Then explicitly release the objects to which you hold a named variable via a call to Marshall.FinalReleaseComObject() on each object.
That's it. :-)
I discussed this in more detail in a previous post, along with a code example.
PIAs are .NET interop wrappers. This means that in the object's destructor (or Dispose - I can't remember) will automatically handle its reference count. The trick is that some references won't be released until the garbage collector is executed. It depends on what the COM object instantiates. For instance, a COM object that opens database cursors will keep those cursors alive in memory until the reference count on those cursors is released. With the .NET/COM interop, the references aren't released until the garbage collector executes or you explicitly release the reference using Marshal.ReleaseComObject (or FinalReleaseComObject).
I personally haven't worked with the Microsoft Office PIAs, but under most circumstances, you shouldn't have to explicitly release the references. It is only when your application starts to lock other resources or crash that you should start being suspicious about dangling references.
EDIT: If you run into a situation where you do need to cleanup COM/Interop objects, use Marshal.FinalReleaseComObject - which takes the reference count all the way to zero instead of just decrementing by one - and set the object reference to null. You can explicitly force garbage collection (GC.Collect) if you really want to be safe, but be careful of doing GC too often as it does invoke a noticeable performance hit.
There are some good practices here using a managed wrapper..worth checking out..
Maybe it's just my superstition, but I decided to explicitly release the Office PIA via Marshal.ReleaseComObject() because when my application crashed, the references to Excel and Word were staying open. I didn't dig too deep into why (stupid deadlines), but releasing them as part of my class's dispose pattern fixed that problem.
You do need to do so if you want the instance of the Office application to exit, as described in this post.
And it's difficult to get it right in all but the most simple scenarios.
There's one simple rule about .Net/COM interop - When in doubt, always Release(). :-)
My experience shows that you have to, otherwise (at least Outlook) the application may not shut down at all.
But this opens another can of worms, as it looks like the RCWs are per process, thus you can break some other addin, which happens to have a reference to the same object.
I have posted a related question here, but I still have no clear answer. I'll edit this post once I know more.