[转]C++ 堆栈溢出的原因以及可行的解决方法
棧溢出(stackoverflow)的原因及解決辦法
大家都知道,Windows程序的內(nèi)存機(jī)制大概是這樣的:全局變量(局部的靜態(tài)變量本質(zhì)也屬于此范圍)存儲(chǔ)于堆內(nèi)存,該段內(nèi)存較大,一般不會(huì)溢出;
函數(shù)地址、函數(shù)參數(shù)、局部變量等信息存儲(chǔ)于棧內(nèi)存,VC++6中棧內(nèi)存默認(rèn)大小為1M,對于當(dāng)前日益擴(kuò)大的程序規(guī)模而言,稍有不慎就可能出問題(動(dòng)態(tài)申請的內(nèi)存即new出來的內(nèi)存不在棧中),即如果函數(shù)這樣寫:
void test_stack_overflow()
{
char *pdata = new[2 * 1024 * 1024];
delete[]pdata;
}
是不會(huì)出現(xiàn)這個(gè)錯(cuò)誤的,而這樣寫則不行:
void test_stack_overflow()
{
char chdata[2 * 1024 * 1024];
}
大多數(shù)情況下都會(huì)出現(xiàn)內(nèi)存溢出的錯(cuò)誤,不信在VC++6中隨便做個(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è)我沒試過但我想沒有誰會(huì)把調(diào)用深度作那么多。檢查是否是此原因的方法為,在引起溢出的那個(gè)函數(shù)處設(shè)一個(gè)斷點(diǎn),然后執(zhí)行程序使其停在斷點(diǎn)處,然后按下快捷鍵Alt+7調(diào)出callstack窗口,在窗口中可以看到函數(shù)調(diào)用的層次關(guān)系。
第二種情況比較常見了,我就是犯了這個(gè)錯(cuò)誤,我在函數(shù)里定義了一個(gè)局部變量,是一個(gè)類對象,該類中有一個(gè)大數(shù)組,大概是1.5M。
解決辦法大致說來也有兩種:
1>增加棧內(nèi)存的數(shù)目
2>使用堆內(nèi)存增加棧內(nèi)存
第一種解決辦法:在VC++6種依次選擇Project->Setting->Link,在Category中選擇output,在Reserved中輸入16進(jìn)制的棧內(nèi)存大小如:0x10000000,然后點(diǎn)ok就可以了。
其他編譯器也有類似的設(shè)置,個(gè)人認(rèn)為這不是一個(gè)好辦法,有一個(gè)致命原因,不知道有沒有人遇到過,我把棧內(nèi)存改大后,與數(shù)據(jù)庫建立不了連接了(ADO方式,Acess數(shù)據(jù)庫),還有遇到調(diào)用CreateThread會(huì)提示棧不夠而創(chuàng)建線程失敗,把棧內(nèi)存還原,問題立刻消失。
不知道究竟是什么原因,有知道的可以告訴我。
第二種解決辦法是比較可行的,具體實(shí)現(xiàn)由很多種方法可以直接把數(shù)組定義改成指針,然后動(dòng)態(tài)申請內(nèi)存;也可以把局部變量變成全局變量,一個(gè)偷懶的辦法是直接在定義前邊加個(gè)static,呵呵,直接變成靜態(tài)變量(實(shí)質(zhì)就是全局變量)。即可以把上例中的函數(shù)這么寫:
void test_stack_overflow()
{
static char chdata[2 * 1024 * 1024];
}
當(dāng)然,除非萬不得已,盡量不要使用這么大的數(shù)組,出現(xiàn)這種情況多半說明程序結(jié)構(gòu)有問題。
總結(jié)
以上是生活随笔為你收集整理的[转]C++ 堆栈溢出的原因以及可行的解决方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库 sqlite 进阶
- 下一篇: 从零开始写网站登录爆破(一)