【问题标题】:Stack trace skipping functions堆栈跟踪跳过函数
【发布时间】:2020-07-06 02:29:55
【问题描述】:

我正在查看 F# 中生成的堆栈跟踪,它们正在跳过函数。一个测试用例:

let foo() =
    failwithf "foo"

[<EntryPoint>]
let main argv =
    foo()
    0

使用调试信息编译,然后运行:

(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

它说异常是从main 生成的,但没有提到它实际生成的位置foo

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

【问题讨论】:

    标签: .net debugging exception f# stack-trace


    【解决方案1】:

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

    请注意,对于fsc,优化是turned on by default。 它们是:

    内联

    foo() 甚至没有被调用——它是一个简单的静态方法,可以轻松内联。 生成的 IL 等价于:

    let main argv =
        PrintfModule.PrintFormatToStringThenFail(new PrintfFormat<_>("foo"));
        0
    

    我们可以用--optimize-关闭它

    fsc -g --optimize- Program.fs
    

    但这还不够。因为……

    尾调用优化

    尾调用优化可让您避免为函数分配新的堆栈帧。 foo 是一个简单的函数,它可以缩短 main。而且由于没有堆栈帧,因此您不会在堆栈跟踪中看到它。

    我们可以使用--tailcalls- 关闭此功能。

    要获得完整的调试体验,请使用 VS 对 DEBUG 所做的基本操作:

    fsc --debug:full --define:DEBUG --define:TRACE --optimize- --tailcalls- Program.fs
    

    现在如果我们运行我们的目标,我们会得到预期的堆栈跟踪:

    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
    

    【讨论】:

      猜你喜欢
      • 2012-06-19
      • 2018-07-13
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 2011-05-25
      • 2011-05-13
      相关资源
      最近更新 更多