StackTrace is not what you think it is

After you realize that stepping through your code for hours is not going to cut it for serious bug tracking in your code, you might look into doing some logging.

Of course, in your log entries you want to have rich information about the assembly, the type and the method that are currently executing.

This is where you would turn to System.Reflection and System.Diagnostics.StackTrace to learn about the methods up in the call stack.

For production code, this is a bad choice. Relying on reflection has the smell of a missed chance in declarative programming. And it’s commonly cause of performance issues.

But StackTrace is one of those things that should be in the namespace RootOfAllEvil™. In its constructor it let’s you specify how much frames it should skip from the actual stack.

This number cannot ever be correct in release code in the wild.

Unless you have used The Force, are running a debug build or in the debugger anyway, the JIT compiler is free to inline any method it thinks is a good choice. And this makes a whole lot of frames disappear from your stack trace, especially your little wrapper around new StackTrace(skipFrames). And now, accessing stackTrace.GetFrame(iSkip) may or may not return null, depending on circumstances you can’t possibly fathom.

This makes your program run fine in the debugger on your machine but fail on your customers’ installations.

Do not use StackTrace in common execution path of your release builds. It is useless and utterly unreliable and it hurts performance.

Do not fix the skipFrames parameter using magic that relies on the JIT compiler architecture or the inlining style you observe. There is soon going to be a JIT or an architecture that breaks your code.

Do not throw an exception to get a more reliable stack trace. This makes it worse.

Do not create an extra assembly for retrieving the stack trace just because you can then walk up until you find another assembly. In interop scenarios you caller may have the nice name Invoke.

Do not ship debug builds to your customers because of bugs in the release builds due to use of StackTrace you cannot find. Try harder.

Do define meaningful identifiers for use by your logging infrastructure. This will also help keep your logs readable.

Do try to implement StackTrace using unmanaged C++ to get a feeling of what it actually takes.

Advertisements
This entry was posted in Software Development. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s