adrift in the sea of experience

Monday, July 16, 2007

Using System.Diagnostics.StackTrace to leave debugging clues.

When I am debugging, I often find myself wishing I could step back to a certain point, in order to discover at which point some piece of data becomes corrupted. Most of the time, it is possible to set a conditional breakpoint which will break the program at the point where something unexpected happens, and reproduce the bug again.

However, this does not always work. Let's say for example that some piece of code is calling Dispose on an instance which it doesn't own, and therefore shouldn't dispose. Things will go haywire when the instance is used after being disposed. At that point, it may be hard to determine the culprit who called Dispose. And because of the number of instances being created and disposed, it may very well be impractical to set a breakpoint in Dispose and inspect each call to it!

What we need here is a way to see who called Dispose in the past.
The way I do this in .NET is by setting a field to a new System.Diagnostics.StackTrace in Dispose just for debugging. Then when things go haywire and the debugger breaks, I simply read the stacktrace to discover the culprit. This trick can be used in any programming language or environment which supports the runtime generation and inspection of stacktraces.

In visual studio 2005, you could also avoid modifying your code by inserting a tracepoint with the following expression:
Instance with hashcode {GetHashCode()} was disposed. Call stack: $CALLSTACK
Then when things go haywire, you can inspect the hashcode of the corrupted instance and search for it in the trace log.