rwa*_*ace 3 .net debugging f# exception stack-trace
我正在查看在 F# 中生成的堆栈跟踪,它们正在跳过函数。一个测试用例:
let foo() =
failwithf "foo"
[<EntryPoint>]
let main argv =
foo()
0
Run Code Online (Sandbox Code Playgroud)
使用调试信息编译,并运行:
(torch) C:\t>fsc -g test.fs
Microsoft (R) F# Compiler version 10.8.0.0 for F# 4.7
Copyright (c) Microsoft Corporation. All Rights Reserved.
(torch) C:\t>test
Unhandled Exception: System.Exception: foo
at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1637.Invoke(String message)
at Test.main(String[] argv) in C:\t\test.fs:line 7
Run Code Online (Sandbox Code Playgroud)
它说异常是从 生成的main,没有提到foo它实际生成的位置。
如何获取完整的堆栈跟踪,包括实际生成异常的函数?
您一直是优化的受害者,这使得在任何工具链中调试都很困难。
内联
foo()甚至没有被调用——它是一个简单的静态方法,可以很容易地内联。由此产生的 IL 相当于:
let main argv =
PrintfModule.PrintFormatToStringThenFail(new PrintfFormat<_>("foo"));
0
Run Code Online (Sandbox Code Playgroud)
我们可以关闭它 --optimize-
fsc -g --optimize- Program.fs
Run Code Online (Sandbox Code Playgroud)
但这还不够。因为...
尾调用优化
尾调用优化可让您避免为函数分配新的堆栈帧。foo是一个简单的函数,它缩短了main. 由于没有堆栈帧,您在堆栈跟踪中看不到它。
我们可以用 关闭它--tailcalls-。
要获得完整的调试体验,请使用 VS 的基本功能DEBUG:
fsc --debug:full --define:DEBUG --define:TRACE --optimize- --tailcalls- Program.fs
Run Code Online (Sandbox Code Playgroud)
现在,如果我们运行我们的目标,我们会按预期获得堆栈跟踪:
Unhandled Exception: System.Exception: foo
at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1639.Invoke(String message)
at Program.foo[a]() in Program.fs:line 4
at Program.main(String[] argv) in Program.fs:line 13
Run Code Online (Sandbox Code Playgroud)