1. 程式人生 > >遞迴函式對棧記憶體的使用

遞迴函式對棧記憶體的使用

遞迴函式由於在運算中,重複的遞迴呼叫自身,函式的區域性變數所佔用的記憶體空間持續增長並不會被釋放,導致區域性變數所佔用的棧記憶體可用空間越來越少,當遞迴呼叫深度達到一定量級,就可能會使得棧記憶體空間不足,導致記憶體分配失敗。所以當設計遞迴函式的時候要注意遞迴的深度所可能達到的上限,避免該情況的發生。
另外一種解決方案是,修改Project的棧空間預留大小,在VS工程中,該值預設為1Mb。
VC6.0中修改堆疊大小的方法:

1. 選擇 "Project->Setting".
2. 選擇 "Link".
3. 選擇 "Category"中的 "Output".
4. 在 "Stack allocations"中的"Reserve:"中輸入棧的大小,單位為位元組,例如: 10000000

在VS2010中設定堆疊大小的方法為:

1. 選擇 "專案->屬性". (Project->Properties)
2. 選擇 "連結器".(Link)
3. 選擇 "系統".(System)
4. 在 "堆疊保留大小"中輸入棧的大小,單位為位元組,例如: 10000000。(Stack Reverse Size: 10000000)

我寫了一個控制檯程式來說明這種情況:

// RcursiveTest4StackMemory.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

#define RCURSIVECOUNT 1000      //遞迴呼叫深度上限

// 遞迴函式 [2/6/2017 ZG-L]
// 每次遞迴給vec加一個元素,由於vec是區域性變數,所以其從棧中分配記憶體
void
RcursiveFunc(vector<int> vec,int count) { vec.push_back(0); count++; if (count<RCURSIVECOUNT) { RcursiveFunc(vec, count); } } // 主函式 [2/6/2017 ZG-L] int main() { vector<int> vec; int count = 0; RcursiveFunc(vec, count); cout << "Done!" << endl; return
0; }

該測試程式通過改變巨集定義RCURSIVECOUNT的值來測試遞迴函式對棧記憶體的使用情況。

測試1:RCURSIVECOUNT設定為1000

#define RCURSIVECOUNT 1000

測試結果:通過

這裡寫圖片描述

測試2:RCURSIVECOUNT設定為10000

#define RCURSIVECOUNT 10000 

測試結果:程式崩潰 崩潰原因:Stack Overflow (記憶體溢位)

這裡寫圖片描述

測試3:RCURSIVECOUNT設定為10000,並修改棧空間預留大小為10000000(≈10Mb)

#define RCURSIVECOUNT 10000

這裡寫圖片描述

測試結果:通過

這裡寫圖片描述

測試結果可以較清晰的說明上述問題,及對應的解決方案。