1

我试图理解一个问题,虽然我读了很多书,但我似乎找不到任何资源来解释这种奇怪的组合。

经过一些实验,我发现设置编译器优化开/关和为 AnyCPU/x86 平台构建的组合改变了 StackFrame.GetFileLineNumber() 的行为

我不明白为什么我得到以下结果(在我的 x64 系统上)

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

下面的代码重现了该问题。

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());
        }
    }
}

如果您将上述代码保存为code.cs使用以下脚本创建批处理文件,它将编译程序集以轻松解决问题:

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
4

1 回答 1

0

当您打开优化时,您是在告诉 JITter 采取不同的行为。

一些函数调用被合并到其他函数调用以保存堆栈帧、展开循环等。MSIL 的结构可以/将会发生巨大变化。

崩溃可能是因为函数调用被折叠并且您尝试提取的堆栈帧不存在。从第 10 行跳转到第 12 行显然是由于编译器对指令进行改组以获得最佳性能。

只是我的 0.02 美元 :)

于 2011-02-23T06:29:02.747 回答