2015-08-31 193 views
-7

我正在用下面的代碼堆棧溢出錯誤:故障解決堆棧溢出錯誤

void f { 
    f(); 
} 

int main() { 
    f(); 
    return 0; 
} 

任何想法,爲什麼?

+5

「*堆棧溢出問題通常是由損壞的註冊表項引起的。*」* LOL * – alk

+0

這是沒有基本情況的遞歸 - >無限循環 – sam

+2

這是一個巨魔,我打賭...... :-) – alk

回答

2

問題是功能f自己調用。這會造成無限循環,導致堆棧崩潰並導致程序崩潰。

你期待這個功能應該做什麼?

void f { 
    f(); 
} 
1

第一個函數(f)是一個遞歸函數。在每次撥打f時,將再次調用功能f。這會導致創建新的堆棧幀。現在,沒有退出條件,因此f將被重複調用。最終,您將用完堆棧框架,併發生stackoverflow。

有兩種方法可以解決這個問題。

1.使用尾遞歸優化。
爲此,如果使用gcc,請使用-O2進行編譯。所以,使用下面的命令。
gcc -O2 $filename -o $executableName 這將針對尾遞歸優化f,本質上創建一個無限循環,而不是在程序集中創建跳轉和鏈接。
請注意,尾遞歸優化只有當你在函數中做的最後一件事情是調用另一個函數(也就是說,如果你最後一件事情導致不再需要堆棧幀),它將起作用。

2.添加退出條件
這取決於你想要做什麼。假設你想遞歸三次。然後,您需要在每次通話時將參數傳遞給f。然後,在f中,檢查退出條件是否爲true。如果是這樣,只需return。如果不是,則用一個新參數再次調用f

+1

這個答案(1)只有在你認爲OP會選擇一個鎖定的程序並且必須手動殺死一個崩潰的程序時纔有意義。我不明白你爲什麼這麼說。 –

+1

@ChrisBeck好吧,我假設OP公佈了代碼作爲例子。也就是說,在遞歸調用'f'中的'f'之前,OP可能會有一些代碼,包括退出條件。在這種情況下,如果遞歸調用在達到退出條件之前可能超過堆棧幀限制,則尾遞歸變得有用。 – nehcsivart