在 GHCi 内的包模块中调试 IO

标签 debugging haskell ghci

我正在 Haskell 中进行低级 IO(用于库绑定(bind)),并且遇到了段错误。我想使用 GHCi 的 :break 来弄清楚发生了什么,但发生的情况是这样的:

> import SDL
> :break SDL.setPaletteColors
cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted

由于有问题的代码不在我自己的模块内,而是在外部包的模块内,因此它作为编译代码加载,显然我不能在编译模块上使用 :break

GHCi manual确认这一点并提供提示:

There is one major restriction: breakpoints and single-stepping are only available in interpreted modules; compiled code is invisible to the debugger[5].

[5] Note that packages only contain compiled code, so debugging a package requires finding its source and loading that directly.

我们直接尝试一下:

> :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?),但在这一点上,这似乎是一种非常尴尬的做事方式,我没有进一步追求它。

编辑:

我实际上尝试过并得到了令人困惑的结果:

> :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 的好方法是什么?

附加说明:

  1. 我确实有需要调试的包的源代码;事实上,它已通过 cabal sandbox add-source

    添加到项目中
  2. 使用 GHCi 的另一种选择是向包源添加跟踪,但这是一个不幸的选择,因为它涉及在每次修改时重新编译包(每当我需要有关执行和修改的更多信息时)痕迹),这需要很长时间。使用 GHCi 进行交互式调试似乎是完成这项工作的更好工具,只要我知道如何使用它就好了。

最佳答案

Stack对此有一些支持。运行 stack ghci --load-local-deps $TARGET 将加载您的项目以及 stack.yamlpackages 字段中的任何依赖项,包括它们是否被标记为 extra-dep。然后断点就可以工作了。您可以通过运行 stack unpack $PACKAGE 并将其添加到 stack.yaml 中的 packages 来调试 GHCi 中的依赖项。

但这并不是万能药。如果包具有冲突的包全局语言扩展(或其他动态标志)或模块名称冲突,则它将无法工作。例如,如果您的顶级包具有 default-extensions: NoImplicitPrelude 而您的依赖项没有,则它们不会导入 prelude,并且几乎肯定不会加载。请参阅this GHC bug .

关于在 GHCi 内的包模块中调试 IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28570367/

相关文章:

haskell - Haskell 中的反向函数行为

haskell - 带/不带显示约束的 GHCi 值的不同行为

Java:调试时如何查找对象地址?

c# - 编码的 UI 测试现在收到有关未找到 Newtonsoft.json 的错误

debugging - 使用 GCC 将程序的源代码嵌入到其二进制文件中以供 GDB 稍后使用

haskell - 在 Haskell 中打印 float

haskell - 在元素第一次出现时拆分列表

c - GDB 中断 ptrace 和其他 API 调用在 OS X Mavericks 上不起作用

haskell - 如何在 Windows 上运行 Threepenny-gui 示例

haskell - typeOf 带有类型构造函数 *->*/从程序中打印值的类型