AFAIK,有两种方法可以获取调用堆栈以在Haskell中进行调试:
HasCallStack
约束ghc -prof -fprof-auto-top
编译代码我的测试代码:
import GHC.Stack
-- | a wrapper function to make "last" from base traceable
last' :: HasCallStack => [a] -> a
last' xs = case xs of [] -> error "abuse last"; _ -> last xs
-- | a untraceable partial function
foo :: [Int] -> Int
foo xs = last' xs + 1
-- | a untraceable partial function
-- , which looks like traceable, but it's call stack is cut off by "foo"
bar :: HasCallStack => [Int] -> Int
bar xs = foo xs
-- | an empty list
-- , which is also an improper input of "last'"
xs :: [Int]
xs = []
-- | the program is expected to print a call stack telling how "bar" is called
-- , but we can only know that "foo" called "last'" improperly from the printed call stack
main :: IO ()
main = print $ bar xs
以下是我通过this测试代码从以上两种方式获得的调用堆栈:
$ ghc -prof -fprof-auto call-stack-cut-off.hs
$ ./call-stack-cut-off
call-stack-cut-off: abuse last
CallStack (from HasCallStack):
error, called at call-stack-cut-off.hs:5:29 in main:Main
last', called at call-stack-cut-off.hs:9:10 in main:Main
CallStack (from -prof):
Main.last' (call-stack-cut-off.hs:5:1-60)
Main.foo (call-stack-cut-off.hs:9:1-21)
Main.bar (call-stack-cut-off.hs:14:1-15)
Main.main (call-stack-cut-off.hs:24:1-21)
Main.CAF (<entire-module>)
IMO,来自
-prof
的调用堆栈已经足够好,并且更易于使用。所以我想知道为什么还添加了HasCallStack
机制。这两种方式之间是否存在一些差异,这些差异会显着影响调试体验? 最佳答案
HasCallStack
具有一些基本优点:
-prof
,因此不需要重新编译(因为配置文件代码与非配置文件代码具有不同的ABI)HasCallStack
约束的位置以及使用withFrozenCallStack
的位置,您可以更好地控制调用堆栈中包括的内容,以防止无关的/内部的详细信息显示在轨迹getCallStack
从程序内部访问调用堆栈,因此您可以将其合并到消息中以进行日志记录,异常等关于haskell - 既然我们在GHC中已经有了 `HasCallStack`,为什么还要提供 `ghc -prof -fprof-auto-top`机制呢?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56641366/