關於大小端以及GCC堆疊保護

2021-09-24 15:15:07 字數 2549 閱讀 1008

一、大小端

寫一段** 測試機器是大端還是小端?

#include #include int main()

輸出結果c=78表示是小端模式 如果輸出結果c=12則為大端模式

到底什麼是大小端?

大端模式,是指資料的高位元組儲存在記憶體的低位址中,而資料的低位元組儲存在記憶體的高位址中,這樣的儲存模式有點兒類似於把資料當作字串順序處理:位址由小向大增加,而資料從高位往低位放;

小端模式,是指資料的高位元組儲存在記憶體的高位址中,而資料的低位元組儲存在記憶體的低位址中,這種儲存模式將位址的高低和資料位權有效地結合起來,高位址部分權值高,低位址部分權值低,和我們的邏輯方法一致

對於十六進製制資料ox12345678 低位元組資料78存放在記憶體的低8位 0x12存放在記憶體的高8位(24~32) --小端模式 反之為大端模式

大小端現狀

(1)intel的80×86系列晶元使用小端儲存模式

(2)arm晶元預設採用小端,但可以切換為大端

(3)mips晶元採用大端,但可以在大小端之間切換

(4)在網路上傳輸的資料普遍採用的都是大端

大小端轉換的**

#define switch16(n)			(((n & 0x00ff) << 8) | ((n & 0xff00) >> 8))

#define switch32(n) (((n & 0x000000ff) << 24) | ((n & 0xff000000) >> 24) | ((n & 0x00ff0000) >> 8) | ((n & 0x0000ff00) << 8))

對於乙個位元組的資料 不存在大小端問題 這裡主要是16位數或者32位數在儲存時高低位到底是低位址還是高位址 網路傳輸時到底是先傳輸高位還是地位

二 、gcc堆疊保護

gcc編譯器關於堆疊保護有如下的三種選項 預設堆疊保護是開啟的 如果禁用堆疊保護可以加編譯選項-fno-stack-protector

(1)-fstack-protector:

啟用堆疊保護,不過只為區域性變數中含有 char 陣列的函式插入保護**

(2)-fstack-protector-all:

啟用堆疊保護,為所有函式插入保護**。

(3)-fno-stack-protector:

禁用堆疊保護。

如下的這段測試**

#include #include int main()

; for(;i<=3;i++)

printf("exit...\n");

}

在linux系統上直接使用gcc test.c 命令編譯執行 執行結果如下:

如果gcc 編譯時去掉堆疊保護 加加上編譯選項-fno-stack-protector

程式執行後發現會無限迴圈的列印hello world…

那麼這裡具體是什麼原因呢?

由於我們的迴圈條件中i<3 錯誤的寫成 了i<=3 當i=3時attr[3]=0 這個時候由於attr[3]陣列訪問 已經越界 此時實際是變數i的值變成了1 導致了無限迴圈。

那麼為什麼訪問了越界的陣列值 卻實際是改了變數i的值呢?這裡我們在做乙個測試 對於如下的測試**:

#include #include int main()

; printf("i_addr=%d\n",&i);

printf("attr[0]=%d\n",&attr[0]);

printf("attr[1]=%d\n",&attr[1]);

printf("attr[2]=%d\n",&attr[2]);

printf("attr[3]=%d\n",&attr[3]);

printf("exit...\n");

}

直接gcc test.c 編譯執行結果如下:

從列印的位址來看 我們而已看到 main函式定義的變數attr[3]的位址和i的位址不是乙個

如果去掉堆疊保護,即編譯時加上編譯選項-fno-stack-protector 在編譯執行 結果如下:

我們發現 此時變數attr[3]的位址正好就是變數i的位址 因此我們越界訪問變數attr[3]實際上就是更改了變數i的值導致程式陷入了死迴圈。

那麼gcc編譯器的堆疊保護又是什麼原理呢?去掉堆疊保護後訪問的越界元素的位址和加上堆疊保護後訪問的越界元素的位址又不一樣了?

這裡網上查了下資料

對於越界訪問的變數 編譯器會放置乙個保護變數值 如果該值被修改了 編譯器就會丟擲異常或錯誤。

關於大小端的問題

討論大小端的問題就是在討論低位元組儲存在低位址還是高位址的問題 大小端記憶方式 例題 unsigned int a 0x1234 unsigned char b unsigned char a 在32位大端模式處理器上變數b等於 解析 unsigned int a 0x1234的32位完全表示是0x...

網路位元組序以及大小端

記憶體中的多位元組資料相對於記憶體位址有大端和小段之分,磁碟檔案中的多位元組資料相對於檔案中的偏移位址也有大端和小端之分,網路資料流同樣有大端小端之分,那麼如何定義網路資料流的位址呢?傳送主機通常將傳送快取區中的資料按記憶體位址從低到高的順序發出,接收主機把從網路上接到的位元組依次儲存在接受緩衝區中...

程式中關於堆疊大小的劃定

昨天在做 小豬登山 的題目碰到了陣列容量太大的問題,今天做乙個總結。首先,參考了slyar的文章 c語言 全域性變數和區域性變數的大小限制 直接貼上。include int main 編譯執行後發現溢位錯誤。include int a 1000000 全域性變數 int main 編譯執行後正常。在...