2013-08-29 87 views
3

我有以下遞歸方法。我得到一個錯誤堆棧溢出。它停在-9352。我的問題是堆棧溢出和無限循環一樣嗎?因爲這將繼續調用自己。瞭解遞歸vs循環ruby

但是,如果我做了一個無限循環與while,直到,等等,它不會給我同樣的堆棧溢出錯誤。它只是繼續下去,直到我的系統內存不足。

這是使用紅寶石

def recursion(n) 
    print n 
    recursion(n-1) 
end 

recursion(3) 

輸出:

3 
2 
1 
0 
. 
. 
. 
-9352 stack overflow stops 
+1

請寫下您正在使用的編程語言。 – Naetmul

回答

-1

遞歸和循環是可以解決不同的方式類似的問題(如在評論中提到的,他們是圖靈等同的技術,但這不是我的領域)。

每個函數調用都會將一幀添加到調用堆棧。這需要額外的內存,並且隨着呼叫鏈越深,它需要更多的內存,直到超過一定的限制,這會使您的堆棧和您的程序崩潰。

您的遞歸代碼爲調用堆棧添加了越來越多的幀,並且在給定有限內存量的情況下,會導致溢出。您需要一些方法來告訴遞歸什麼時候停止,並在內存耗盡之前這樣做。這種情況在數學歸納中相當於base case,因此通常這樣稱呼。

在評論中指出的另一種選擇是利用Tail call優化,它取代了堆棧中的當前幀,因此可以防止堆棧溢出。

您的迭代解決方案只需要固定數量的內存。

只有計數器或其他預定義變量的被更改,因此它不會產生任何內存開銷。

如果不限制輸出,理論上它可以無限期地繼續,但其他一些耗盡或錯誤很可能會導致它失效。但是,這不會是循環本身使用的變量所消耗的內存。

+1

遞歸和迭代並沒有根本的不同,因爲遞歸相當於while循環。另外,堆棧溢出發生點的含義是一些基本的常數,在誤導和錯誤之間。如果您考慮違反您的基本原則的尾調優化遞歸,您的整個帖子也完全不正確。 –

+0

雖然我同意你關於圖靈等價的問題(雖然我承認沒有深入的知識,但這不是我的研究領域),但我努力保持答案簡單並處理具體案例。我不考慮任何編譯器優化或邊緣情況,因爲我只想說明在他的示例中需要基本情況​​。至於堆棧綁定AFAIK,它是在編譯時或程序啓動過程中確定的。我會編輯我的答案以反映您的評論,隨時編輯它或張貼您自己的答案。 – MasterAM

+0

尾調用優化與大多數函數式語言和所有gcc編譯語言中使用的邊界情況相差甚遠。您可能正在考慮在程序啓動或編譯之前定義的進程內存。堆棧大小是進程內存的一部分,具體取決於當前分配給堆棧的內存量與堆的大小。堆內存隨程序執行而改變,因此對於許多語言來說,確定可用堆棧空間是不可能的。發佈一個簡單的答案併發佈一個非常不正確的答案也有所不同。 –