我正在 Haskell 中进行低级 IO(用于库绑定)并且遇到了段错误。我想使用 GHCi:break弄清楚发生了什么,但发生的事情是这样的:
> import SDL
> :break SDL.setPaletteColors
cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted
由于有问题的代码不在我自己的模块内,而是在外部包的模块内,因此它作为编译代码加载,显然我无法使用:break在已编译的模块上。
GHCi 手册 https://www.haskell.org/platform/doc/2014.2.0.0/ghc/users_guide/ghci-debugger.html#idm39475824768证实了这一点并提供了提示:
有一个主要限制:断点和单步只能在解释模块中使用;编译后的代码对于调试器是不可见的[5]。
[5] 请注意,包仅包含已编译的代码,因此调试包需要找到其源代码并直接加载。
我们直接尝试一下:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
some_path/sdl2/src/SDL/Video/Renderer.hs:101:8:
Could not find module ‘Control.Monad.IO.Class’
It is a member of the hidden package ‘transformers-0.3.0.0’.
Perhaps you need to add ‘transformers’ to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
我可以将依赖项添加到我的 .cabal 文件中,但这已经感觉不对了。一旦我这样做了:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
some_path/sdl2/src/SDL/Video/Renderer.hs:119:8:
Could not find module ‘SDL.Internal.Numbered’
it is a hidden module in the package ‘sdl2-2.0.0’
Use -v to see a list of the files searched for.
我可以将这些模块公开(可能?通过修改包 .cabal?),但在这一点上,这似乎是一种非常尴尬的做事方式,我没有进一步追求它。
EDIT:
我实际上尝试过并得到了令人困惑的结果:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
[1 of 1] Compiling SDL.Video.Renderer ( some_path/sdl2/src/SDL/Video/Renderer.hs, interpreted )
Ok, modules loaded: SDL.Video.Renderer.
> :break SDL.setPaletteColors
cannot set breakpoint on SDL.setPaletteColors: module SDL.Video.Renderer is not interpreted
我(未经教育的)猜测:这是因为外部模块仍然以二进制形式链接到我的代码,并且在解释模式下动态加载它不会改变这一点。
所以,总结一下这个问题:在外部包中调试 IO 的好方法是什么?
补充笔记:
-
我确实有我需要调试的包的源代码;事实上,它已添加到项目中cabal 沙箱添加源
-
使用 GHCi 的另一种选择是将跟踪添加到包源中,但这是一个不幸的选择,因为它涉及每次修改时重新编译包(每当我需要有关执行和修改跟踪的更多信息时),并且需要很长时间。使用 GHCi 进行交互式调试似乎是完成这项工作的更好工具,只要我知道如何使用它就好了。