Wednesday, October 05, 2011

That Tricky StackTrace

This post is a copy of my second quiz on GeekQuiz.Net called Walking Up the StackTrace.

This question is very simple: what does this application print and why? The answer may not be as simple as you think.

using System;

namespace StackTrace
{
    class Program
    {
        static void Main()
        {
            Method1();
            Console.ReadLine();
        }

        static void Method1()
        {
            var stackTrace = new System.Diagnostics.StackTrace(1);
            var stackFrame = stackTrace.GetFrame(0);
            Console.WriteLine(stackFrame.GetMethod().Name);

            Method2();
        }

        static void Method2()
        {
...
...

static void Method3()
        {
            var stackTrace = new System.Diagnostics.StackTrace(1);
            var stackFrame = stackTrace.GetFrame(0);
            Console.WriteLine(stackFrame.GetMethod().Name);
        }
    }
}

Feel free to run it!!

At the first look and even when you run it the answer seems to be:

Main

Method1

Method2

which is right but not always! In fact, in production (i.e. in release mode) that answer is always wrong!! Let me explain:

Obviously StackTrace is populated at RunTime and not at compile time. When you are debugging this application or even when you are running it when it is built with 'debugging' configuration the StackTrace is what you would hope it to be, which is what I wrote above. However if you run the very same application in release mode, the situation is different.

At RunTime, when it comes the time for JIT compiler to compile this module, it has a look at the methods and thinks to itself: "Hey, you know what. These calls are very simple and I could inline these methods and save myself, CPU and memory from a lot trouble. This way we will not have to deal with pushing addresses into stack and popping them up later. So I am just going to inline this. This not only performs better but is also really cool. So yeah, let's do it". OK, maybe JIT does not think like this; but the result is the same! :)

So what is going to happen at RunTime in release mode (and depending on your machine's CPU architecture) is that JIT is going to inline these methods and the application output all of a sudden becomes:

Main

Main

Main


Read more: Mehdi Khalilis blog
QR: that-tricky-stacktrace

Posted via email from Jasper-Net