2015-02-17 25 views
18

我正在做Haskell中的低級IO(用於庫綁定),並且遇到段錯誤。我想用GHCI的:打破弄清楚發生了什麼事情,但在這裏會發生什麼:GHCi中的包模塊中調試IO

> 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的好辦法?

其他注意事項:

  1. 我有源的包,我需要調試;事實上,它被添加到項目中與陰謀沙箱添加源

  2. 另外一種方式來使用GHCI將跟蹤添加到包源,但是這是一個不幸的選擇,因爲它涉及到重新編譯每次修改時的包(每當我需要更多關於執行和修改跟蹤的信息時),這需要很長時間。使用GHCi進行交互式調試似乎是這項工作的更好工具,只要我知道如何使用它。

+0

你已經得到了比我更進一步。我甚至不知道如何使用GHCi的調試功能,當它們*可用時 - 我應該在某個時候真正使用RTFM。對你的一個建議是:雖然段錯誤可能肯定是由於使用'unsafeCoerce'或'unsafePerformIO'不當引起的,但從不安全的數組/矢量引用中得到它們似乎更常見。你正在使用的不安全操作是否具有安全的等價物,比如'write'而不是'unsafeWrite'?如果是這樣,使用安全版本進行測試,然後切換到不安全的版本可以使事情更容易處理。 – dfeuer 2015-02-17 22:53:50

+1

@dfeuer:在這種情況下,正如我今天所發現的那樣,segfault實際上來自於對一個指針(「Ptr a」)的解引用,它的底層內存已經被軟件包使用的C庫(libSDL2)釋放了。那完全是我自己的錯。但問題仍然存在,因爲我不得不求助於Debug.Trace,而且在更復雜的情況下可能需要很長時間。 – 2015-02-18 19:27:26

+0

只是爲了確保 - 你是否用'cabal configure --ghc-option = -fPIC'或類似的配置來配置? sdl2自述文件提到它。 – schellsan 2016-12-14 22:22:23

回答

0

堆棧對此有一些支持。正在運行stack ghci --load-local-deps $TARGET將加載您的項目以及packages字段stack.yaml中的任何依賴項,包括它們被標記爲extra-dep s。那時斷點會起作用。您可以通過運行stack unpack $PACKAGE並將其添加到packagesstack.yaml來調試GHCi中的相關性。

然而,這不是萬能的。如果軟件包具有衝突的軟件包全局語言擴展(或其他動態標誌)或模塊名稱衝突,則不起作用。例如,如果您的頂級軟件包有default-extensions: NoImplicitPrelude,而您的依賴關係沒有,則它們將不會導入前奏,並且幾乎肯定不會加載。請參閱this GHC bug