3

Recently, I fixed a leak where an event held an instance alive. It took only a few weeks and I had to fix a leak for the same object again, because someone added another event which caused a leak.

I was now thinking of adding some automatic tests. This test should create the object, destroy the object and validate that the object is not in memory any more.

I guess it's not possible to write some code like:

Initialize();
var object = CreateObject();
Type type = object.GetType();
DestroyObject(object);
// There are a few objects that intentionally keep my object still alive
// up to a certain time.
DestroyFurtherObjectsWithReferenceToMyObject();
GC.Collect();
Assert.IsNull(FindInstanceOf(type));

I think the problem is the FindInstanceOf-method. The GC class, afaik, does not provide a method like that.

Another approach would be creating the object very often, destroying it each time, and then comparing total memory.
I feel this approach is less reliable. In my case, I have to pull up many parts of the application first (thus Initialize above). After creating and destroying the object, I need to destroy some further objects holding a reference.
If changes are made to those other objects, this could have some bad effects on my test. Don't want to go too much into detail here, but it's not unlikely that my test may eventually fail for random reasons.

So, what would be a possible solution to find out if a certain object stays in memory?

Em1
  • 1,077
  • 18
  • 38
  • There are known rules why would object will stay in memory. Those can be pointed out by compile time deterministic or how are they called (*Code Analysis*, *Resharper*). Anything outside of their scope you shouldn't test imho. They will be found by running production code in test environment and fought then. – Sinatr May 28 '14 at 10:12
  • Btw, this question was asked several times already: [click](http://stackoverflow.com/q/3652028/1997232), [click](http://stackoverflow.com/q/23007772/1997232). – Sinatr May 28 '14 at 10:16
  • You could adapt this technique http://ayende.com/blog/4826/challenge-stop-the-leaks – CodesInChaos May 28 '14 at 10:18

1 Answers1

2

There is no API exposed for this. However, you can "emulate" work that some collectors do. Behind the curtains, some GC types simply keep a map

object reference <=> usage counter

When some other object points to the current one, usage counter is incremented. When reference is released, counter gets decremented. What you can do, is to have a usage map for your object which you can check in your test. Sample code

Initialize();
var object = CreateObject();  // calls ObjectUsageMap.IncrementCountFor(object);
DestroyObject(object);        // calls ObjectUsageMap.DecrementCountFor(object);

// calls ObjectUsageMap.DecrementCountFor(object) inside next line
DestroyFurtherObjectsWithReferenceToMyObject(); 
GC.Collect();
Assert.AreEqual(0, ObjectUsageMap.GetCountFor(object));
oleksii
  • 35,458
  • 16
  • 93
  • 163