棧溢出(stackoverflow)的緣由及解決辦法數據庫
你們都知道,Windows程序的內存機制大概是這樣的:全局變量(局部的靜態變量本質也屬於此範圍)存儲於堆內存,該段內存較大,通常不會溢出;數組
函數地址、函數參數、局部變量等信息存儲於棧內存,VC++6中棧內存默認大小爲1M,對於當前日益擴大的程序規模而言,稍有不慎就可能出問題(動態申請的內存即new出來的內存不在棧中),即若是函數這樣寫:函數
void test_stack_overflow()spa
{線程
char *pdata = new[2 * 1024 * 1024];指針
delete[]pdata;對象
}遞歸
是不會出現這個錯誤的,而這樣寫則不行:內存
void test_stack_overflow()編譯器
{
char chdata[2 * 1024 * 1024];
}
大多數狀況下都會出現內存溢出的錯誤,不信在VC++6中隨便作個程序,調用一下這個函數試式。
出現棧內存溢出的常見緣由有2個:
1>函數調用層次過深,每調用一次,函數的參數、局部變量等信息就壓一次棧。
2>局部靜態變量體積太大
第一種狀況不太常見,由於不少狀況下咱們都用其餘方法來代替遞歸調用(反正我是這麼作的),因此只要不出現無限制的調用都應該是沒有問題的,起碼深度幾十層我想是沒問題的,這個我沒試過但我想沒有誰會把調用深度做那麼多。檢查是不是此緣由的方法爲,在引發溢出的那個函數處設一個斷點,而後執行程序使其停在斷點處,而後按下快捷鍵Alt+7調出callstack窗口,在窗口中能夠看到函數調用的層次關係。
第二種狀況比較常見了,我就是犯了這個錯誤,我在函數裏定義了一個局部變量,是一個類對象,該類中有一個大數組,大概是1.5M。
解決辦法大體說來也有兩種:
1>增長棧內存的數目
2>使用堆內存增長棧內存
第一種解決辦法:在VC++6種依次選擇Project->Setting->Link,在Category中選擇output,在Reserved中輸入16進制的棧內存大小如:0x10000000,而後點ok就能夠了。
其餘編譯器也有相似的設置,我的認爲這不是一個好辦法,有一個致命緣由,不知道有沒有人遇到過,我把棧內存改大後,與數據庫創建不了鏈接了(ADO方式,Acess數據庫),還有遇到調用CreateThread會提示棧不夠而建立線程失敗,把棧內存還原,問題馬上消失。
不知道到底是什麼緣由,有知道的能夠告訴我。
第二種解決辦法是比較可行的,具體實現由不少種方法能夠直接把數組定義改爲指針,而後動態申請內存;也能夠把局部變量變成全局變量,一個偷懶的辦法是直接在定義前邊加個static,呵呵,直接變成靜態變量(實質就是全局變量)。便可以把上例中的函數這麼寫:
void test_stack_overflow()
{
static char chdata[2 * 1024 * 1024];
}
固然,除非萬不得已,儘可能不要使用這麼大的數組,出現這種狀況多半說明程序結構有問題。