遞歸

2014-03-28 142 views
1

我運行在MATLAB遞歸函數,並得到該錯誤消息時超出堆棧空間:500達到遞歸

「最大遞歸限制使用set(0,‘RecursionLimit’,N) 改變極限。請注意,超出你的可用堆棧空間可能會使MATLAB和/或你的電腦崩潰。

我想知道,如果我改變遞歸限制並超過我的堆棧空間,是否真的會發生MATLAB和/或我的電腦崩潰?對我來說似乎很難。爲什麼MATLAB不會自動停止並在可用堆棧空間被超過時自動退出?

我如何知道我可以選擇沒有危險的遞歸極限?

+0

它肯定會退出。只是不以非常友好的方式。如果沒有足夠的堆棧空間,則沒有足夠的空間來顯示友好的消息。這個網站有一個很好的理由,堆棧溢出是*討厭*錯誤。 –

+0

我不認爲有一個安全的方法來選擇限制,但如果您將可用空間的數量除以函數的一個實例使用的數量,您可以瞭解上限。 –

回答

1

計算機不會崩潰。 Matlab可能會依賴於它們對堆棧的處理。最有可能的警告是因爲Matlab是多平臺的,它可以運行在許多不同的操作系統和體系結構上,其中一些可能不如Windows或大多數POSIX那樣安全。

實際上,在Windows機器上使用線程堆棧時,「堆棧溢出」錯誤實際上是「訪問衝突」 - 您嘗試訪問不屬於您的內存實際上並非訪問衝突(相反,它基本上是一種特殊類型的頁面錯誤),但這個想法是相似的 - 操作系統首先通知您,您已達到堆棧的上限,並且如果超過了最後幾個「安全」頁面,它會給你實際的堆棧溢出。這非常方便,因爲它是「免費」的 - 您不必檢查每次您是否還有堆棧空間push,並且它爲您提供了一些額外的安全性。

取決於Matlab如何處理該異常,它可能優雅地報告錯誤並繼續,或者可能會崩潰。

當然,處理堆棧溢出可能非常棘手,但不適用於操作系統。 Windows可以很好地處理這些錯誤,它並不真正關心。

遞歸限制很大程度上取決於Matlab實際上在遞歸的每個步驟中必須存儲多少數據。 Windows線程的典型堆棧大小約爲256-1024kB(並且可以自行開始配置線程),這實際上相當多,除非你傳遞了很多大的論據。考慮到使用兩個整數並且沒有任何變量的方法,您甚至需要大約20 000次深度遞歸來超過256 kiB堆棧空間(在32位上)。

但是,堆棧溢出通常是代碼中的問題。你通常選擇錯誤的遞歸退出條件來遇到它們。這就是堆棧溢出由「異常」處理而不是爲堆棧分配更多內存的原因之一 - 每個微不足道的遞歸錯誤都會導致所有應用程序甚至操作系統崩潰。所以,首先確保你確實需要一個深度遞歸:)

+0

你有一些細節錯誤,[這篇文章](http://stackoverflow.com/a/22467611/17034)可能有幫助。 –

+0

@HansPassant謝謝你,現在它離家更近了嗎? – Luaan

0

其實here is a very similar question presented by Mathworks

這裏是他們怎麼說你就可以生產遞歸問題,我覺得它有一點32位,所以你可能需要增加5000:

創建以下文件:

function retVal = myrecursivefun(inVal, recursions) 
recursions = recursions - 1; 
inVal = inVal + 1; 

if recursions > 0 
retVal = myrecursivefun(inVal, recursions); 
else 
retVal = inVal; 
end 

然後運行如下崩潰MATLAB:

set(0,'RecursionLimit', 5000); 
myrecursivefun(1, 5000); 

個人註釋:我覺得默認的重500的詛咒限制是有道理的。 Matlab程序員通常不會想要超越這個,大多數情況下這個限制是由於一個錯誤而造成的。

另外,我認爲matlab比C++等低級語言有更多的函數調用開銷,因此您通常首先要避免深度遞歸。