Get active references to an object
I am looking for a managed/unmanaged API that will allow开发者_StackOverflow me to find which objects reference another object and are potentially keeping it from being garbage collected.
Such an API might look like this:
var foo = new Foo();
var bar = new Bar();
bar.Foo = foo;
var references = GC.GetReferencesTo(foo);
// references is an array that contains bar
I know profilers can be used for this but I'd like to make it part of a unit test. Is there a managed or unmanaged API that I could use?
The unmanaged dll SOS (Son Of Strike) provides a means to achieve this, though I do not believe it has significant scripting support, nor does it provide a simple means to achieve this via a single command. You would have to introspect the variable's address, check all gcroots for the variable (which would include the stack obviously) and deal with the remainder.
I would suggest that, if you wish to prove that an object is not referenced, a simpler technique would be to (temporarily) make it finalizeable, ensure it is no longer referenced on the stack of your unit test and then force several garbage collections via GC.Collect() then use GC.WaitForPendingFinalizers().
Your finalize method can set a static boolean flag and then your unit test can assert this is true.
I would question the utility of this without further explanation but this is likely to be the simplest method of proving no dangling references exist in a unit test.
.NET Profiler uses the profiling API to trace the graph of objects. You might be particularly interested in callback methods ObjectReferences
and RootReferences
, and maybe also ObjectAllocated
. The first two methods will be called to cover the entire live object graph after every garbage colection, so intercepting them alone is sufficient to rebuild that graph, and then analyze it in any way you want.
This article explains how to put all the pieces together.
Also remember .NET uses traced garbage collection so objects referenced by other objects - e.g. a graph of objects - will still be cleaned up by the GC if your app isn't referencing any of them any longer; it's a lot smarter than the classic reference counting garbage collection algorithms pre-.NET. This means that even when you find a way to pinpoint all references to an object, some of them may not matter and may not need to be taken care of.
This doesn't answer directly how to find all references to an object, but does make readers aware of the the situation that, when you do find all references through a tool or utility, some kinds of things don't need to be fixed any longer in .NET - e.g. classic circular references, and therefore you might have to look for some ingenious ways of knowing what to ignore when trying to fix memory leaks.
This explanation only applies to the managed code scenario.
精彩评论