C語言 關於溢位

2021-08-27 10:21:38 字數 1623 閱讀 3904

對於變數的值超出其定義的資料型別的表示範圍,這種情況稱為溢位。

書上以shot型變數為例畫出了溢位的二進位制原理,如圖1。

[color=blue]圖1:[/color]

[img]

圖中變數a換算成十進位制為32767,變數b換算成十進位制為3,本意想得到32770,不過由於溢位,得到的結果變數c換算成十進位制為-2。

上機演示後,計算機輸出的結果卻和理論上的不一樣,變數c為-32767,並不是原理上的-2,如圖2。

[color=blue]圖2:[/color]

[img]

為什麼會有這種情況?難道是溢位的原理不是書上那樣?

帶著這個疑問,我又試驗了a=32766時,b=1、b=2和b=3三種情況。變數c對應的值為32767、-32768和-32767。如圖3、圖4、圖5:

[color=blue]圖3:[/color]

[img]

[color=blue]圖4:[/color]

[img]

[color=blue]圖5:[/color]

[img]

當b=1時,變數c剛好達到shot型的臨界範圍;當b=2和b=3時,變數c的結果已經和理論值不一樣。但是聯絡圖2,我發現,計算機得到的溢位的值也是有規律的,即從shot型的最小值開始遞增。

[color=red]由此猜想:[/color]計算機在記憶體中為每個變數[color=red]單獨且連續[/color]分配了65535個位元組的空間,裡面儲存了從-32768到32767的數值,計算機在做加法時,是先找到變數a的值的對應記憶體位址,然後按照變數b的值查詢記憶體位址,最後再將那個位址裡的值賦予變數c(例如變數b的值為1,則在變數a當前值往下找一格,得到的值再賦予變數c)。

為了證明我的猜想,做了如下試驗:當a=32766,b=32770時,c=?

如果猜想是正確的,那麼變數c的值應該是從a=32766這一值所在的記憶體位址,往下移動32770格後,其記憶體位址儲存的值,即為0,如圖6。

[color=blue]圖6:[/color]

[img]

值得注意的是:變數b的值,並不是輸入的32770,顯示的是-32766。由於變數abc都是short型,所以32770已經超出了範圍,按照猜想,由於32770=32767+3,b此時的值應該是b=32767所在的記憶體位址往下移三格後,其記憶體位址儲存的值。

至此,我沒發現任何與猜想相悖的情況,但為了保險起見,又做了如下試驗:當a=32766,b=65537時,c=?

由於65537=32767+32770已經超出了short的範圍,所以b的值應該是b=32767所在的記憶體位址往下移動32770格後,其記憶體位址儲存的值,即為1。

而變數c的值應該是從a=32766這一值所在的記憶體位址,往下移動65537格後,其記憶體位址儲存的值,為32767,如圖7。

[color=blue]圖7:[/color]

[img]

由此可見,猜想是符合實際情況的。

另外,對比圖3和圖7,雖然變數c的值都為32767,但是兩圖中32767的**卻不一樣。在圖3中,計算機是在記憶體位址中把short型變數a的最大值32767賦予變數c;而在圖7中,計算機是在記憶體位址中把short型變數b的最大值32767賦予變數c。

結論:書上溢位的原理是正確的,只是由於計算機的工作方式等原因,才會使計算機輸出的結果和理論上不一樣。

棧溢位攻擊c語言 棧溢位攻擊

我們先來看下面的乙個例子 include int main gets str printf str s n str return 0 在 main 函式內部定義乙個字元陣列,並通過 gets 為它賦值。在vs2010 debug模式下執行程式,當輸入的字元不超過10個時,可以正確輸出,但是當輸入的字...

談談C語言的溢位

溢位是c語言中最常見的漏洞。最常見的溢位包括 陣列溢位 數溢位 緩衝區溢位 指標溢位 以及棧溢位 下面筆者就對這些溢位做乙個總結歸納。1 陣列溢位 陣列溢位是最常見的一種溢位。因為在c語言中,含n個元素的陣列下標是從0開始,到n 1結束,而且c語言沒有提供陣列越界檢查的機制。請看如下 上面的迴圈判定...

關於記憶體溢位

記憶體溢位是指應用系統中存在無法 的記憶體或使用的記憶體過多,最終使得程式執行要用到的記憶體大於虛擬機器能提供的最大記憶體。1 記憶體中載入的資料太大 2 集合類中有對物件的引用,使用後未清空 3 中存在死迴圈或迴圈產生過多重複的物件實體 4 使用的第三方軟體中的bug 5 啟動引數記憶體值設定的過...