2013-10-23 54 views
0

任何遞歸都可以修改爲堆棧結構的迭代函數,那麼爲什麼我要這樣做呢?如果答案是爲了避免計算器溢出,那麼計算機如何通過遞歸溢出?爲什麼編譯器會自動默認或使用其他關鍵字將堆遞歸函數放入堆棧中?我理解堆也是有限的,但它比分配給程序的堆棧大得多。爲什麼由遞歸引起的stackoverflow無法解決?

+3

堆不是無限要麼... –

+2

[尾遞歸函數(http://stackoverflow.com/questions/33923/what-is-tail-recursion/33928#33928)可被重新寫爲迭代函數,但許多遞歸函數不是尾遞歸的。 – Simon

+0

每個進程都在32位計算機上獲得4GB虛擬內存,其中2GB分配給操作系統數據結構。因此堆棧的大小受到限制並可能溢出。 –

回答

0

激活記錄確實可以分配堆,但通常認爲這太昂貴。儘管有一些採用這種方法的實現:例如,Stackless Python和SML/NJ。

在這些情況下,動機可能是幫助執行延續,而不是「修復」堆棧溢出。

0

根據C/C++ maximum stack size of programMSDN,Windows上的最大堆棧大小爲1 MiB。你的問題很有趣。關鍵字肯定是可能的,編譯器可以做到這一點。你需要問編譯器製造商,但我想這不是一個非常有趣的功能。

由於堆棧上的其他局部變量以及堆上的遞歸簿記變量,緩存將很困難。信息分散在內存中。一些遞歸算法可以轉化爲真正的迭代算法(如計算Factorial),甚至可以轉化爲封閉形式的表達式(例如參見Fibonacci numbers)。然後,不需要記錄遞歸調用。

+0

DEFAULT最大堆棧爲1(和VS!= windows) –

0

在迭代過程中,您可以自己跟蹤遞歸狀態。

如果編譯器能夠使用非常通用的過程機制(其效率可能受到各種ABI問題的阻礙),那麼可以更高效地實現這一點。

堆棧檢查是可能的,但在所有系統上並不容易,因爲並非所有系統都使用固定堆棧或線性地址空間。它當然也有開銷,因爲檢查被添加到每個遞歸中。