[轉]C++ 堆棧溢出的原因以及可行的解決方法


棧溢出(stackoverflow)的原因及解決辦法

大家都知道,Windows程序的內存機制大概是這樣的:全局變量(局部的靜態變量本質也屬於此范圍)存儲於堆內存,該段內存較大,一般不會溢出;

函數地址、函數參數、局部變量等信息存儲於棧內存,VC++6中棧內存默認大小為1M,對於當前日益擴大的程序規模而言,稍有不慎就可能出問題(動態申請的內存即new出來的內存不在棧中),即如果函數這樣寫:

void test_stack_overflow()

{

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];

}

當然,除非萬不得已,盡量不要使用這么大的數組,出現這種情況多半說明程序結構有問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM