I ran into something surprising today when a program I wrote to test a second program ended up with an Out Of Memory exception. That really shouldn't have happened. Sure, it was creating a complicated model, and was doing what would normally happen over the course of an entire year, or more, but I still felt that it shouldn't have run out of memory. Therefore, I delved into the profiling tools in VS, which have changed quite a bit since I last looked at them. What I'm asking about is specifically the .NET Object Allocation Tool and what to make of some results I'm seeing. I'm not sure if anybody has used this tool all that much, but here's the question:

There is an object that is created and passed as an argument to a method. Inside that method, the object gets passed around to a series of other methods. The object is just a vessel for a series of simple things which are usually just strings, Booleans, and so forth. It's an ugly object, so I won't show it here. The question applies as to this object, but there's a simpler object that is one of the members of the ugly object, and it makes a much nicer example for a question. This inner object has just two members, a GUID and a Date. This is added to the ugly object such that it can be used by the methods that get that ugly object. This inner object can be called EW, for convenience.

When looking at the profile, I was a bit surprised to see that there were 53,694 EW objects in the allocations. I think this makes sense. As it turns out, EW objects are a member of the ugly object, but are also members of some other objects that are used in events. The model can spawn a LOT of events, especially when I'm simulating a years worth of use. However, I would expect that virtually all of these EW objects would simply be unreachable. Once the event that held them is over, nobody is holding references to them, and the event argument is now gone.

So, the first question is: Is there any way to determine, in the output of the allocation tool, whether an object is still reachable, or not? I don't see a means.

I have an outrageous number of lists and dictionaries, but most of them are ephemeral, like that EW object that is just used as a member of some event argument. It's just a vessel to pass a GUID and a Date around for the use of whoever wants it. Once the event is over, the vessel is no longer of any use, and should be unreachable. I expect it to remain in memory, because I understand that it is easier to allocate new than to recover old, so perhaps what I'm seeing is 85,500 Dictionaries, of which a dozen are used and the rest are unreachable, and so forth.

If that's the case, then why am I getting an Out Of Memory exception? Sure, there are hundreds of thousands of items allocated. Heck, there are over 68,000 GUIDs allocated, but virtually all of them are unreachable. Shouldn't the GC automatically recover memory rather than throwing an exception?

Of course, if those objects are still held by something, then they can't be recovered, but that really shouldn't be the case.