Haskell 如何在ghc 7.10.3中按零划分生成堆栈跟踪?

Haskell 如何在ghc 7.10.3中按零划分生成堆栈跟踪?,haskell,stack-trace,partial-functions,Haskell,Stack Trace,Partial Functions,如果程序运行时出现“除以零”的消息而崩溃,那么识别该错误在代码中何处产生的最佳方法是什么?GHC不支持堆栈跟踪,因为没有调用堆栈。您最好在基本模块中使用模拟堆栈跟踪机制 从GHC 7.8开始,并在7.10.3中提供,GHC.Stack公开 errorWithStackTrace :: String -> a 其作用类似于正常构建上的error,但使用SCC注释(例如,来自--fprof auto)在已分析的构建上构建近似堆栈跟踪。您将需要重新编译并启用评测以支持此功能。如果你使用阴谋集团

如果程序运行时出现“除以零”的消息而崩溃,那么识别该错误在代码中何处产生的最佳方法是什么?

GHC不支持堆栈跟踪,因为没有调用堆栈。您最好在基本模块中使用模拟堆栈跟踪机制

从GHC 7.8开始,并在7.10.3中提供,
GHC.Stack
公开

errorWithStackTrace :: String -> a
其作用类似于正常构建上的
error
,但使用SCC注释(例如,来自
--fprof auto
)在已分析的构建上构建近似堆栈跟踪。您将需要重新编译并启用评测以支持此功能。如果你使用阴谋集团,你可以逃跑

cabal configure --enable-library-profiling --enable-executable-profiling
重建

从GHC 8.0开始,不推荐使用
errorWithStackTrace
,并且由
HasCallStack
机器提供对调用站点生成的支持

现在从
GHC.Stack
文档中引用

函数可以使用
HasCallStack
约束请求其调用站点。例如,我们可以定义

errorWithCallStack :: HasCallStack => String -> a
作为
error
的一个变体,它将获得其调用站点。我们可以使用
callStack
访问
errorWithCallStack
中的调用堆栈

errorWithCallStack :: HasCallStack => String -> a
errorWithCallStack msg = error (msg ++ "n" ++ prettyCallStack callStack)
因此,如果我们调用
errorWithCallStack
,我们将在错误消息旁边得到一个格式化的调用堆栈

>>> errorWithCallStack "die"
*** Exception: die
CallStack (from HasCallStack):
  errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1
调用堆栈“die”时出错 ***例外:死亡 调用堆栈(来自HasCallStack): errorWithCallStack,在interactive:Ghci1中于:2:1调用 (我猜是
msg++“\n”
的意思,但是
“n”
是写的。)


虽然使用GHC 7.8及更高版本可以获得一些非常有限的堆栈跟踪支持,但如果可能,我建议升级到GHC 8以获得更好的支持。无论哪种方式,它都不会像你从其他语言中习惯的那样,但总比没有好。

你能称之为“最佳”吗?一般来说,堆栈跟踪在惰性函数式语言中并不像您可能期望的那样有意义,所以您的“最佳”选择可能是启用评测。否则,请使用。我想我会接受任何在源代码中标识出错行的方法。当您说启用评测时,这是否意味着我可以使用一些额外的参数(哪些参数?)运行
stack build
,然后当我执行程序时,它将伴随错误提供更多信息?在最新的GHC版本中,
error
errorWithCallStack
。文档似乎建议您从概要构建中获得比使用
HasCallStack
更好的堆栈跟踪。我还没有尝试过这种分析方法。@d我是否正确理解GHC 8.2.1 w/
-prof
应该产生更好的调用堆栈的说法?事实似乎并非如此:即使启用了评测(通过
堆栈构建--profile
),我也只看到错误消息“除以零”,没有额外的上下文。假设有一个代码库,其中除法操作(
/
`div`
)出现在几十个调用站点上。当一个人在运行时遇到错误消息“除以零”,并且这些调用站点中的任何一个似乎都有可能成为错误源时,如何进行调试?必须用注释版本替换除法操作的每个实例吗(最好是在二进制搜索中缩小有问题的调用站点)?@ThomasM.DuBuisson,我真的不知道,但是看看@ThomasM.DuBuisson
-prof
,使用
-fprof auto
或手动添加的SCC注释可以创建更具描述性的调用堆栈。