trying to chase down some memory problems

Working on a UI application and having severe memory bloat. Doing some reading, ANTS seemed like a pretty cool tool. And it is!

However, I am having some problems chasing down some of my problems. I am creating a custom UserControl on a Panel and then doing the equivalent of "New Document" which is supposed to purge all of these custom controls from the panel.

When I do this, I call Dispose on each user control in the panel before clearing all of the panels controls.

Using your tool I noticed that my object was still on the heap. It looked like every event handler that i subscribed to still had a reference (20+ references to my object). So I unsubscribed them all using the -= (minus, equals) method.

Now I still have 5 references left and I dont know how to fix these:
Object[]ID 1 -- 4096 bytes
EventHandlerList ID 196690 -- 16 bytes
VScrollProperties ID 195258 -- 40 bytes
HScrollProperties ID 195257 -- 40 bytes
Control+ControlNativeWindow ID 195253 -- 56 bytes

The other interesting thing is that if I create another user control and take a snapshot, instead of there being two objects on the heap (my leaked one, and the new one), there is only one. If I clear the panel again, it returns to 1. If I add 3, I only see 3, but when I clear, it returns to 1. It seems like this one object never goes away.

Any advice you have would be greatly appreciated.



  • Hi,

    I'm not sure exactly what's causing what you see, but here's something to try: before taking a snapshot, click the "Force GC" button on the ANTS UI to force a garbage collection, then take the snapshot.

    The reason for this is that although we do force a garbage collection as part of the snapshot process, objects that require finalization only get moved to the finalization queue on the first GC, then collected on the second. This can lead to objects that have actually "died" still apparently being live in ANTS.

    Another thing to check on those references you have left is what actually references them - it could be that most of them are just "local" to the object in question (i.e. object 1 references object 2 which references object 1), and so won't actually prevent the objects from being collected once the first one becomes unreachable.

    My last suggestion would be to take a look at the Call Stack panel (you might need to make this visible from the View menu) - this shows the call stack at which each object was allocated, which might make it easier to determine what object it actually is.

    Hope that helps,
    Robert Chipperfield
    Red Gate
  • Hi Robert,

    Thanks for your response.

    I have been doing a Force GC. That does not seem to help with this problem.

    Also, those 5 references I listed do all seem to be "local" to the object in question. If I click them, the navigator jumps to that object and it shows them being referenced only by the object I am hoping will go away.

    Finally, I do know the type of the object I am dealing with, and I do know where it is being allocated. I am just trying to figure out why it is sticking around :)

    Any other ideas?

  • Hi,

    The other thing you could check is whether the object in question is listed as a "root object" - these are objects that are defined as being reachable even if there aren't any other references pointing to them.

    I forget the exact criteria for being a root object, but it's along the lines of:
    - Referenced by a static field of some class
    - A local variable in one of the frames on the current call stack
    - On the finalization queue (we've probably ruled this one out)
    (There might be another couple, but I think those are the main ones).

    You'll find a "root object" field available in the hierarchy grid - if you right-click on the column titles, and select "choose columns", it should be available there.

    Hope that helps,
    Robert Chipperfield
    Red Gate
  • Brian DonahueBrian Donahue Posts: 6,590 New member
    Is there a chance that these objects are pinned? If you use perfmon.exe and add the .NET Memory object and the '#pinned objects' counter to the surface for the instance of the process you are profiling, it should tell you how many pinned objects are in that process. If an object has been pinned for some reason, the garbage collector would not free the object.
  • Sorry, I have been unavailable to respond until today.

    The object is not a root object. It also does not appear to be pinned. I never used perfmon before, so I am not quite sure what I was doing. But looking at the graph of pinned objects, it did not appear to fluctuate when doing the operations in question.
Sign In or Register to comment.