StackFrame.GetFileLineNumber() 行为因程序集平台和优化标志而异
我正在尝试理解一个问题,尽管我读了很多书,但我似乎找不到任何资源来解释这种奇怪的组合。
经过一番实验后,我发现设置编译器优化开/关和为 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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您打开优化时,您就是在告诉 JITter 以不同的方式表现。
一些函数调用被合并到其他函数中以保存堆栈帧、展开循环等。MSIL 的结构可以/将会发生巨大的变化。
崩溃可能是因为函数调用已折叠并且您尝试提取的堆栈帧不存在。从第 10 行跳转到第 12 行显然是由于编译器为了获得最佳性能而对指令进行了改组。
只是我的 0.02 美元:)
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 :)