jmi*_*ite 3 debugging haskell ghc ghci
我正在尝试在Haskell中调试一个庞大而复杂的程序,我自己并没有完全写出来.
我正在尝试打印我的数据结构以诊断错误,但是当我这样做时,我收到以下错误:error: Prelude.undefined
.如您所见,此错误非常无法提供信息.
我有理由相信这是来自我已"部分"初始化的记录,我正在尝试访问其值尚未设置的字段.
程序(编译器)分布在两个cabal项目,一个库和一个使用该库的可执行文件中.这使得使用GHCI/cabal-repl进行调试很困难:我无法在可执行文件上运行GHCi,因为它不是错误的来源,但重新创建可执行文件给库提供的输入太复杂了,无法手工完成.
我想知道:我该怎么做才能获得有关创建错误记录的位置,错误来源的哪个字段等的更多信息.是否有RTS选项或我可以用来提供更多错误输出信息的内容?
如果您-Wall
在cabal文件的ghc-options中使用它,它将发出不完整记录的警告.
module Foo where
data Bar = Bar { bar :: String, baz :: String }
f = Bar { baz = "foo" }
Foo.hs:5:5: Warning:
Fields of ‘Bar’ not initialised: bar
In the expression: Bar {baz = "foo"}
In an equation for ‘f’: f = Bar {baz = "foo"}
Ok, modules loaded: Foo.
Run Code Online (Sandbox Code Playgroud)
使用-Wall(或-Werror)进行编译是找到未初始化字段源的良好开端.但是,它可能不是错误的来源.缺少记录字段初始化有一个特定的错误消息:
Prelude> data A = A { a :: Int } deriving Show
Prelude> A {}
A {a = *** Exception: <interactive>:11:1-4: Missing field in record construction a
Run Code Online (Sandbox Code Playgroud)
如果向记录字段添加严格性注释,则在编译时将抛出错误:
Prelude> data A = A { a :: !Int } deriving Show
Prelude> let a = A { }
<interactive>:26:9:
Constructor ‘A’ does not have the required strict field(s): a
In the expression: A {}
In an equation for ‘a’: a = A {}
Run Code Online (Sandbox Code Playgroud)
查找错误源的另一个选项是在启用分析的情况下进行编译并传递-xc RTS标志.
来自GHC用户指南:https: //downloads.haskell.org/~ghc/latest/docs/html/users_guide/runtime-control.html
-xc(仅在编译程序进行性能分析时可用.)当程序中引发异常时,此选项会将堆栈跟踪转储到stderr.
这对于调试特别有用:如果你的程序抱怨head []错误并且你不知道哪个代码导致它,那么使用-prof -fprof-auto进行编译并运行+ RTS -xc -RTS将在错误被引发的时刻准确地告诉您调用堆栈.
输出包含程序中引发的每个异常的一个报告(程序可能会在执行期间引发并捕获几个异常),其中每个报告看起来像这样:
***引发异常(由于+ RTS -xc报告),堆栈跟踪:GHC.List.CAF - >评估者:Main.polynomial.table_search,
从Main.polynomial.theta_index调用,从Main.polynomial调用,调用来自Main.make_pressure.p调用的Main.zonal_pressure,从Main.make_pressure调用,从Main.compute_initial_state.p调用,从Main.compute_initial_state调用,从Main.CAF调用...