最近在做一個(gè)程序(VC6.0),功能大概有網(wǎng)絡(luò)通信、數(shù)據(jù)庫、繪圖等。測試的時(shí)候程序一運(yùn)行到某個(gè)函數(shù)就出現(xiàn)此錯(cuò)誤,查了很多地方,試了很多解決辦法,終于把問題解決了,寫個(gè)日志提醒一下自己,也希望作為一個(gè)普遍解決辦法讓大家少費(fèi)工夫(其他編譯器也會出現(xiàn)同樣的問題)。
大家都知道,Windows程序的內(nèi)存機(jī)制大概是這樣的,全局變量(局部的靜態(tài)變量本質(zhì)也屬于此范圍)存儲于堆內(nèi)存,該段內(nèi)存較大,一般不會溢出;函數(shù)地址、函數(shù)參數(shù)、局部變量等信息存儲于棧內(nèi)存,VC6中棧內(nèi)存默認(rèn)大小為1M,對于當(dāng)前日益擴(kuò)大的程序規(guī)模而言,稍有不慎就可能出問題。
(動(dòng)態(tài)申請的內(nèi)存即new出來的內(nèi)存不在棧中)
即如果函數(shù)這樣寫:
voidtest_stack_overflow()
{
char* chdata = new[2*1024*1024];
delete []chdata;
}
是不會出現(xiàn)這個(gè)錯(cuò)誤的,而這樣寫則不行:
voidtest_stack_overflow()
{
char chdata[2*1024*1024];
}
大多數(shù)情況下都會出現(xiàn)內(nèi)存溢出的錯(cuò)誤,不信在vc6中隨便做個(gè)程序,調(diào)用一下這個(gè)函數(shù)試式。
出現(xiàn)棧內(nèi)存溢出的常見原因有2個(gè):
1> 函數(shù)調(diào)用層次過深,每調(diào)用一次,函數(shù)的參數(shù)、局部變量等信息就壓一次棧。
2> 局部靜態(tài)變量體積太大
第一種情況不太常見,因?yàn)楹芏嗲闆r下我們都用其他方法來代替遞歸調(diào)用(反正我是這么做的),所以只要不出現(xiàn)無限制的調(diào)用都應(yīng)該是沒有問題的,起碼深度幾十層我想是沒問題的,這個(gè)我沒試過但我想沒有誰會把調(diào)用深度作那么多。檢查是否是此原因的方法為,在引起溢出的那個(gè)函數(shù)處設(shè)一個(gè)斷點(diǎn),然后執(zhí)行程序使其停在斷點(diǎn)處,然后按下快捷鍵Alt+7調(diào)出call stack窗口,在窗口中可以看到函數(shù)調(diào)用的層次關(guān)系。
第二種情況比較常見了,我就是犯了這個(gè)錯(cuò)誤,我在函數(shù)里定義了一個(gè)局部變量,是一個(gè)類對象,該類中有一個(gè)大數(shù)組,大概是1.5M。
解決辦法大致說來也有兩種:
1> 增加棧內(nèi)存的數(shù)目
2> 使用堆內(nèi)存
增加棧內(nèi)存方法如下,在vc6種依次選擇Project->Setting->Link,在Category中選擇output,在Reserve中輸入16進(jìn)制的棧內(nèi)存大小如:0x10000000,然后點(diǎn)ok就可以了。
其他編譯器也有類似的設(shè)置,個(gè)人認(rèn)為這不是一個(gè)好辦法,有一個(gè)致命原因,不知道有沒有人遇到過,我把棧內(nèi)存改大后,與數(shù)據(jù)庫建立不了連接了(ADO方式,Acess數(shù)據(jù)庫),把棧內(nèi)存還原,問題立刻消失。不知道究竟是什么原因,有知道的可以告訴我。
email: la_ariza@sina.com
第二種解決辦法是比較可行的,具體實(shí)現(xiàn)由很多種方法可以直接把數(shù)組定義改成指針,然后動(dòng)態(tài)申請內(nèi)存;也可以把局部變量變成全局變量,一個(gè)偷懶的辦法是直接在定義前邊加個(gè)static,呵呵,直接變成靜態(tài)變量(實(shí)質(zhì)就是全局變量)。即可以把上例中的函數(shù)這么寫:
voidtest_stack_overflow()
{
static char chdata[2*1024*1024];
}
當(dāng)然,除非萬不得已,盡量不要使用這么大的數(shù)組,出現(xiàn)這種情況多半說明程序結(jié)構(gòu)有問題。
愛華網(wǎng)

