Hugs Haskell實現中「Error C stack overflow」的常見原因是什麼?Haskell中「Error C stack overflow」的原因通常爲
回答
如果您習慣於使用尾遞歸因式分解的函數式語言,這可能會出現。假設你有一個函數:
sum = go 0
where
go accum [] = accum
go accum (x:xs) = go (accum+x) xs
,順便說一下,是一樣的
sum = foldl (+) 0
如果我們評估的功能,我們可以看到這個問題:
sum [1,2,3,4]
go 0 [1,2,3,4]
go (0+1) [2,3,4]
go ((0+1)+2) [3,4]
go (((0+1)+2)+3) [4]
go ((((0+1)+2)+3)+4) []
(((0+1)+2)+3)+4
現在,以評估表達式Haskell使用堆棧:
EXPR | STACK
(((0+1)+2)+3)+4 |
((0+1)+2)+3 | +4
(0+1)+2 | +3 +4
(0+1) | +2 +3 +4
1 | +2 +3 +4
3 | +3 +4
6 | +4
10 |
和這個是可能發生溢出的地方。如果您評估了總和[1..10^6],那麼該堆棧將會有一百萬個條目。
但請注意這裏的病理。您只是爲了建立一個巨大的fscking表達式(「thunk」)而遞歸列表,然後使用堆棧來評估它。我們寧願評估它,因爲我們遞歸,通過使尾遞歸嚴格:
sum = go 0
where
go accum [] = accum
go accum (x:xs) = accum `seq` go (accum+x) xs
,上面寫着試圖評估遞歸調用之前評估ACCUM,所以我們得到(這可能需要一定的耐心來了解) :
sum [1,2,3,4]
go 0 [1,2,3,4]
let accum = 0 in accum `seq` go (accum+1) [2,3,4]
go (0+1) [2,3,4]
let accum = 0+1 in accum `seq` go (accum+2) [3,4]
go (1+2) [3,4]
let accum = 1+2 in accum `seq` go (accum+3) [4]
go (3+3) [4]
let accum = 3+3 in accum `seq` go (accum+4) []
go (6+4) []
6+4
10
因此,當我們遍歷列表時,我們計算總和,所以我們不必使用深棧來評估結果。這種改進的尾遞歸模式被封裝在Data.List.foldl」,所以:
sum = foldl' (+) 0
一個好的經驗法則是從不使用與foldl,因爲它總是建立起巨大的thunk。改用foldl'。如果輸出類型具有延遲結構(例如列表或函數),請使用foldr。但是一般來說,避免堆棧溢出沒有銀彈,你只需瞭解你的程序的評估行爲。有時候這可能很難。但是,如果我理解正確,堆棧溢出總是來自嘗試評估一個巨大的thunk,但是。因此,尋找那些可以創建這些地方的地方,並迫使評估更早發生。
+1對foldl的工作原理有很好的解釋 – karoberts 2010-03-17 20:57:33
失控遞歸是最有可能的候選人......您需要提供更多信息,以獲得更準確的答案。
下面是一些代碼,可能導致失控的遞歸:
main =
let x = x :: Int
in print x
這裏會發生什麼事是,當x
在print x
評估它啓動,然後發現,要完成它需要評估x
的評價。
由於TCO(注意x是x中的尾部調用),可能不會導致堆棧溢出。這將是一個無限循環。 – luqui 2010-03-17 14:42:17
嗯...所以它是,luqui。我確信這種代碼在我上次嘗試時產生了堆棧錯誤(不出所料,幾年前)。 – 2010-03-17 15:23:05
糟糕。我是對的,但情況不同。如果我在GHCi中運行該代碼,它就會永遠循環。如果我編譯並運行它,我得到的錯誤:a.out:<
最可能的原因必須是不受控制的遞歸。每次遞歸調用都會爲其輸入/輸出參數消耗更多的堆棧空間。
只有當你正確定義「遞歸」時。 Haskell對什麼消耗堆棧空間比大多數函數式語言有一個完全不同的概念。 – luqui 2010-03-17 14:18:27
- 1. C++中的AVL樹 - Stack Overflow異常
- 2. OpenCV findContours Stack Overflow
- 3. Stack Overflow錯誤android?
- 4. var so = {name:'stack'} ['overflow'];
- 5. Stack Overflow,Redis和Cache失效
- 6. Stack Overflow-esque源代碼
- 7. typesafe stack scala error
- 8. 簡單的用戶註冊,如Stack OverFlow?
- 9. Haskell stack with global ghc
- 10. haskell-stack不安裝QuickCheck
- 11. Xcode標記框架,如Stack Overflow/FB。
- 12. Stack Overflow相關問題算法
- 13. 「Lane User Stack Overflow」調試CUDA程序
- 14. 當您登錄到Stack Overflow時,Stack Exchange如何登錄?
- 15. Stack Overflow如何包含Javascript文件?
- 16. haskell-stack獲取TlsExceptionHostPort錯誤
- 17. 「Stack ........ was corrupted」error while using memcpy
- 18. Haskell Stack中的Win32包問題
- 19. ClassNotFoundException的原因爲檢查異常
- 20. Haskell forall error
- 21. 什麼原因導致「Unknown chromium error:-400」?
- 22. addfooterview原因異常
- 23. 原因在C++
- 24. 堆棧OverFlow平原的Javascript
- 25. Stack Overflow上Python中打印語句的方括號
- 26. 運算符=通常返回對C++中對象的引用的原因?
- 27. 顯示異常的原因
- 28. 這是什麼原因爲stackoverflow異常?
- 29. 理解Stack()的工作原理
- 30. 使用C++和stack/cabal編譯Haskell軟件包
哪個實現?HUGS? NHC? GHC? – 2010-03-17 14:02:20
所有的答案似乎都在談論溢出Haskell運行時的堆棧。 C堆棧不同,至少在GHC中。這是一個令人困惑的錯誤消息,或者是與FFI相關的問題。 (我做了很多FFI工作,從來沒有見過這種情況,但我使用GHC)。 – jrockway 2010-03-18 01:17:34