First of all, many thanks for this excellent and well-written project.
I have used it to build a memory leak checker that dumps the callstack of each leak. The leak checker works by recording the addresses of the callstack for each malloc. When the program exits, the record is examined for unfreed blocks and at that time (not
before!) the symbols (functionName, filename, line number, etc) are resolved and a report is generated.
In order to make this work efficiently, I have had to make a couple of small changes to StackWalker, which I would like to share with you as they may be of general interest.
- Logical separation of Stack Walking and Symbols Resolution. ShowCallstack separated into 2 methods: ShowCallStack() and GetSymbols(). Based on the options flags, the ShowCallstack() method may or may not call the GetSymbols() method. This was done in order
to be able to call GetSymbols from elsewhere also - e.g. at exit time when dumping the recorded callstacks.
- Logical separation of DLL initialization and symbols loading. The first call to ShowCallstack inits the DbgHelp DLLs, the first call to GetSymbols() loads the modules. Why bother? Because for some reason stack walking (even if we don't resolve the symbols
at that time) is 1 to 2 orders of magnitude slower if the modules have been loaded! Anybody know why? (this observation made on an intel running Vista Ultimate, service pack 2).
- OnCallstackEntry() returns a BOOL indicating whether or not to terminate the StackWalk. This is to allow clients to walk up to a maximum depth (helpful, because StackWalking is slow).
I would be happy to share the modified sources with anyone who is interested.
Once again, thanks for a most excellent and useful post.
National Film Board of Canada