堆疊溢位 , 簡而言之, 就是堆棧滿了,還往裡面塞東西。
一、堆疊溢位
堆疊溢位的產生的原因主要有以下幾個方面 1.1 遞迴層級過深
由於過多的函數調用,導致呼叫堆疊無法容納這些調用的返回地址,一般在遞迴中產生。堆疊溢位很可能由無限遞迴(Infinite recursion)產生,但也可能僅僅是過多的堆棧層級。
如下一段代碼:
void foo(){ int a; foo();}int main(){ foo(); return 0;}
運行結果如下:
首先解釋兩個概念:
ESP : 棧指標,用於指向棧幀的棧頂(下一個壓入棧的活動記錄的頂部),而EBP為幀指標,指向當前活動記錄的底部。 棧幀可以理解整個程式棧的子棧,程式棧由子棧構成。Windows中棧的預設大小為2MB。
對於上面的兩張結果圖,根據 ebp指標在減小可以看出,每進入一次遞迴,都會增加一個棧幀(子棧)。而程式棧空間是有限的,當迭代層級過深時,就會導致棧不夠用,此時如果繼續遞迴,則會導致溢出。
1.2 大資料結構的局部變數
局部變數儲存在棧區,如果局部變數的sizeof過大,也將導致棧溢出。但是這種情況,實際中很難遇到。
二、越界
在32bit系統中,char類型佔用1個位元組,其中signed char 的最高位表示符號,也就是只有7bit是表示資料;unsigned char則是所有bit都表示資料。所以,signed char的表示範圍是 -128 ~ 127, unsigned char 的表示範圍是0 ~ 255。
那麼對於如下一段代碼,c1的值是多少。
signed char a = 128; std::bitset<sizeof(char)*8> c(a); //獲得a的二進位標記法cout << c << endl;
結果如下:
也就是-128 ( 負數在電腦中用補碼錶示:反碼+1).
如果繼續進行加減運算,會出現什麼問題。。 其實就是正常的加減法,如128的二進位是 1000 0000 ,那麼在此基礎上面加1就變成了 1000 0001( 即-127),那麼減1呢。就是0111 1111。 如下:
signed char a = 128; // -128signed char d = a - (char)1; // 127
但是對於1111 1111(-1),如果此時,繼續+1, 那麼就變成了1 0000 0000 , 而由於char是8 bit,所以對於這個情況,最高位捨去,最後結果為0000 0000。