堆栈跟踪跳过功能

问题描述 投票:0回答:1

我正在查看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个回答
1
投票

您一直是优化的受害者,这使得调试在任何工具链中都非常困难。对于fsc,优化为turned on by default

Inlining

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
© www.soinside.com 2019 - 2024. All rights reserved.