【发布时间】:2015-02-17 20:18:19
【问题描述】:
我在 Haskell 中执行低级 IO(用于库绑定)并且遇到了段错误。我想使用 GHCi 的 :break 来弄清楚发生了什么,但会发生以下情况:
> import SDL
> :break SDL.setPaletteColors
cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted
由于有问题的代码不在我自己的模块中,而是在外部包中的模块中,因此它作为编译代码加载,显然我不能在编译模块上使用 :break。
GHCi manual 确认并提供提示:
有一个主要限制:断点和单步仅在解释模块中可用;编译后的代码对调试器是不可见的[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?),但在这一点上,这似乎是一种非常尴尬的做事方式,我没有进一步追求。
编辑:
我确实试过了,得到了莫名其妙的结果:
> :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 sandbox add-source
添加到项目中 -
使用 GHCi 的另一种选择是将跟踪添加到包源,但这是一个不幸的选择,因为它涉及在每次修改时重新编译包(每当我需要有关执行和修改跟踪的更多信息时) ,这需要很长时间。使用 GHCi 进行交互式调试似乎是完成这项工作的更好工具,如果我知道如何使用它就好了。
【问题讨论】:
-
你比我走得更远。我什至不知道如何使用 GHCi 的调试功能,当它们可用时——我真的应该在某个时候使用 RTFM。给你的一个建议:虽然段错误可能是由于
unsafeCoerce或unsafePerformIO的不当使用造成的,但从错误的不安全数组/向量引用中获取它们似乎更常见。您正在使用的不安全操作是否具有安全等效项,例如write而不是unsafeWrite?如果是这样,使用安全版本进行测试,然后切换到不安全的版本以提高性能可以让事情更更容易处理。 -
@dfeuer:在这种情况下,正如我今天发现的那样,段错误实际上来自取消引用指针(“Ptr a”),其底层内存已被 C 库(libSDL2)包释放正在使用。那完全是我自己的错。但问题仍然存在,因为我不得不求助于 Debug.Trace,而且在更复杂的情况下可能需要很长时间。
-
只是为了确保 - 您是否使用
cabal configure --ghc-option=-fPIC或类似配置? sdl2 README 提到了它。