堆栈跟踪跳过功能

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它实际生成的位置。

如何获取完整的堆栈跟踪,包括实际生成异常的函数?

Ast*_*sti 7

您一直是优化的受害者,这使得在任何工具链中调试都很困难。

请注意,默认情况下fsc优化是打开的。他们是:

内联

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)