StackFrame.GetFileLineNumber() behaviour varies based on assembly Platform and Optimisation flags

373 views Asked by At

i'm trying to understand a problem and although I've read a lot, I can't seem to find any resources explaining this odd combination.

After a bit of experimentation I've found that combinations of setting compiler optimisations on/off and building for the AnyCPU/x86 platform changes the behaviour of StackFrame.GetFileLineNumber()

I don't understand why i'm getting the following results (on my x64 system)

  Optimisations     | Platform      | Line Number Reported  | Result
 -------------------|---------------|-----------------------|----------
  off               | anycpu        | 10                    | Correct
  off               | x86           | 10                    | Correct
  on                | anycpu        | APPCRASH              | WTF?
  on                | x86           | 12                    | WTF?

The code below reproduces the problem.

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            GetLineNumberOfThisCall();

            Console.WriteLine("\r\nPress any key to exit...");
            Console.ReadKey();
        }

        private static void GetLineNumberOfThisCall()
        {
            var stackTrace = new StackTrace(true);
            var callingFrame = stackTrace.GetFrame(1);

            Console.WriteLine("The call to the stack-walking method was found on line: {0}", callingFrame.GetFileLineNumber());
        }
    }
}

if you save the above code as code.cs create a batch file with the following script, it will compile assemblies to easily repo to the problem:

csc /t:exe /debug+ /out:anycpu-optimisation-on.exe /platform:anycpu /optimize+ code.cs
csc /t:exe /debug+ /out:anycpu-optimisation-off.exe /platform:anycpu /optimize- code.cs
csc /t:exe /debug+ /out:x86-optimisation-on.exe /platform:x86 /optimize+ code.cs
csc /t:exe /debug+ /out:x86-optimisation-off.exe /platform:x86 /optimize- code.cs
1

There are 1 answers

2
OJ. On

When you turn on optimisations you're telling the JITter to behave differently.

Some function calls are merged into others to save a stack frame, loops are unrolled, etc. The structure of the MSIL can/will change drastically.

The crash could be because the function call was collapsed and the stack frame your trying to extract doesn't exist. The jump from line 10 to 12 is obviously due to the compiler shuffling around instructions to get the best perf.

Just my $0.02 :)