views:

123

answers:

6

An application I am working with is exhibiting the following behaviour:

  1. During a particular high-memory operation, the memory usage of the process under Task Manager (Mem Usage stat) reaches a peak of approximately 2.5GB (Note: A registry key has been set to allow this, as usually there is a maximum of 2GB for a process under 32-bit Windows)

  2. After the operation is complete, the process size slowly starts decreasing at a rate of 1MB per second.

I am trying to figure out the easiest way to quickly determine who is freeing this memory, and where it is being free'd.

I am having trouble attaching a memory profiler to my code, and I don't particularly want to override the new/delete operators to track the allocations/deallocations (IOW, I want to do this without re-compiling my code).

Can anyone offer any useful suggestions of how I could do this via the Visual Studio debugger?


Update

I should also mention that it's a multi-threaded application, so pausing the application and analysing the call stack through the debugger is not the most desirable option. I considered freezing different threads one at a time to see if the memory stops reducing, but I'm fairly certain this will cause the application to crash.

A: 

You might find this article useful: http://www.gamasutra.com/view/feature/1430/monitoring_your_pcs_memory_usage_.php?print=1

basically what I had in mind was hooking the low level allocation functions.

dtroy
A: 

A couple different ideas:

  • The C runtime has a set of memory debugging functions; you'd need to recompile though. You could get a snapshot at computation completion and later, and use _CrtMemDifference to see what changed.

  • Or, you can attach to the process in your debugger, and cause it to dump a core before and after the memory freeing. Using NTSD, you can see what heaps are around, and the sizes of things. (You'll need a lot of disk space, and a fair amount of patience.) There's a setting (I think you get it through gflags, but I don't remember) that causes it to save a piece of the call stack as part of the dump; using that you can figure out what kind of object is being deallocated. Unfortunately, it only stores 4 or 5 stack frames, so you'll likely have to do something more clever as the next step to figure out where it's being freed. Either look at the code ("oh yeah, there's only one place where that can happen") or put in breakpoints on those destructors, or add tracing to the allocations and deallocations.

Michael
A: 

If your memory manager wipes free'd data to a known value (usually something like 0xfeeefeee), you can set a data breakpoint on a particular instance of something you're interested in. When it gets free'd, the breakpoint will trigger when the memory gets wiped.

celion
A: 

I recommend you to check UMDH tool that comes with Debugging Tools For Windows (You can find usage and samples in the debugging tools help). You can snap shot running process's heap allocations with stack trace and compare them.

msh
+2  A: 

Ahh! You're looking at the wrong counter!

Mem Usage doesn't tell you that memory is being freed. Only that the working set is being purged! This could mean some other application needs memory, or the VMM decided to mark some of your process's pages as Stand By for some other process to quickly use. It does not mean that VirtualFree, HeapFree or any other free function is being called.

Look at the commit size (VM Size, Private Bytes, etc).

But if you still want to know when memory is being decommitted or freed or what-have-you, then break on some free calls. E.g. (for Visual C++)

{,,kernel32.dll}HeapFree

or

{,,msvcr80.dll}free

etc.

Or just a regular function breakpoint on the above. Just make sure it resolves the address.

cdb/WinDbg let you do it via

bp kernel32!HeapFree
bp msvcrt!free

etc.

Names may vary depending on which CRT version you use and how you link against it (via /MT or /MD and its variants)

Alex
A: 

You could try Memory Validator to monitor the allocations and deallocations. Memory Validator has a couple of features that will help you identify where data is being deallocated:

  • Hotspots view. This can show you a tree of all allocations and deallocations or just all allocations or just all deallocations. It presents the data as a percentage of memory activity (based on amount of memory (de)allocated at a given location).

  • Analysis view. You can perform queries asking for data in a given address range. You can restrict these queries to any of alloc, realloc, dealloc behaviours.

  • Objects view. You can view allocations by type and see the maximum number of objects of each type (plus lots of other stats). Right click on a type to get a context menu, choose show all deallocations - will show deallocation locations for that type on Analysis tab.

I think the Hotspots view may give you the insight you need.

Stephen Kellett