遞迴函式對棧記憶體的使用
阿新 • • 發佈:2018-11-25
遞迴函式由於在運算中,重複的遞迴呼叫自身,函式的區域性變數所佔用的記憶體空間持續增長並不會被釋放,導致區域性變數所佔用的棧記憶體可用空間越來越少,當遞迴呼叫深度達到一定量級,就可能會使得棧記憶體空間不足,導致記憶體分配失敗。所以當設計遞迴函式的時候要注意遞迴的深度所可能達到的上限,避免該情況的發生。
另外一種解決方案是,修改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
測試結果:通過
測試結果可以較清晰的說明上述問題,及對應的解決方案。