重學 語言系列三 變數在記憶體中的布局

2021-06-21 10:57:41 字數 1766 閱讀 5432

這次或許以後的東西不像寫教科書那樣,寫板書來介紹所有的東西,我覺得那樣不如直接給人推薦一本大師的c語言書就好了,我想吧自己學習過程中的思考過程記錄下來,不僅僅是闡述結果,而是結果是怎麼來的,當然這麼寫,很可能隨著思路不知道扯到**,顯的邏輯性不強。但是我還是想記錄下自己的學習方法或者思維方法。  另外我覺得關於記憶體這一塊牽扯的比較多,可能一次講不完,我會繼續補充的。

扯了這麼多,其實我想知道的是程式設計使用變數,它在記憶體中如何儲存?

先粗略的看,記憶體分為使用者模式空間和核心空間,如下圖:

再詳細一點劃分如下:

一步跳到這裡確實有點突兀,一般的介紹應該都是只講堆,棧,資料段,**段

稍微解釋一下,棧中所存放的資料是區域性變數,堆(heap)中存放的是動態分配的記憶體,(malloc/free,new/delete.....)所分配的記憶體

bss("block started by symbol"的縮寫,意味符號開始的塊

)存放的是未初始化的全域性變數和靜態變數,該段變數只有大小,名稱,卻沒有值,是編譯器處理

未初始化資料的地方,一般在程式一開始就會被清零,由於bss段只儲存沒有值的變數,所以事實上它不需要儲存這些變數的映像,執行時所需要的bss段大小記錄

在目標檔案中,但bss段(不像其它段)並不佔據目標檔案的任何空間.

data存放的是已經初始化的全域性變數和靜態變數

text段存放的是二進位制**。

和預想中整整齊齊一塊接一塊的區域不同,各個記憶體區域之間有著隨機偏移值,為什麼要弄這個東西?不是增加了記憶體碎片?

為了弄明白這個東西,我們來試試簡單的緩衝區溢位,拿棧做例子,**如下:

#include#includeint main()

}

測試結果如下:

為什麼會是這樣?

因為只分配了4個位元組給str,  str和access在記憶體中布局如下:

也許你會疑問,為什麼access在記憶體中的位址會在str上面,根據上面整個記憶體的圖,棧中分配方向是從高到低,而在main函式棧幀中,根據**,str應該先分配

才是,我開始也有這個疑問,還準備去stackoverflow去提問,不過在segmentfault中找到了答案,中文的答案看上去要親切一些,解釋如下:

區域性變數的空間不是乙個乙個壓入棧中的,而是一次性分配好的,所以理解為變數依次入棧是錯誤的。c語言也沒有規定區域性變數在記憶體中的位置,只是常常實現為先定義的變數在高位址、後定義的變數在低位址。不過區域性變數在棧上的位置沒有絕對的關係,甚至不一定會出現在棧上

這樣,因為字串函式只是根據\0,來判斷結束,很容易造成溢位的情況,導致程式bug

發現寫了這麼多,好像和主題關係不是那麼明確,決定下篇博文繼續這個主題,好好寫,而當務之急是把這個收尾,緩衝區溢位是問題很嚴重的,而各個段起始位址加上隨機

偏移之後會讓緩衝區溢位變的更加困難,我在後續的文章中會專門討論這個,這裡就簡單pass,接下來真正見識變數在記憶體中的布局吧

剖析程式的記憶體布局

bss段解釋

《c專家程式設計》

變數在記憶體中的儲存

c 中變數在記憶體中的儲存 一 記憶體大致可以分為三部分 區 堆疊區 靜態資料段。c和c 中有全域性變數,靜態變數以及區域性變數等幾類。全域性變數和靜態變數是在編譯的時候就已經分配好在資料段,也就是說在執行main函式之前就已經分配好了位址,如果定義的時候已經初始化,那麼就存放初始化的值,如果沒有初...

變數在記憶體中的儲存

package com.gxlq.ren 該類表示荊楚的老師 public class jcteacher public void playgame 8種基本型別 整數,小數,布林型別,char 字元型別 n 復合 整數 byte 1 short 2 int 4 long 8 小數 float 4 ...

c c 變數在記憶體中的分布

c c 變數在記憶體中的分布在筆試時經常考到,雖然簡單,但也容易忘記,因此在這作個總結,以加深印象。先寫乙個測試程式 執行結果 release版本 如下 可以看出 1.變數在記憶體位址的分布為 堆 棧 區 全域性靜態 常量資料 2.同一區域的各變數按宣告的順序在記憶體的中依次由低到高分配空間 只有未...