C 語言程式的記憶體配置概念教學 - GT Wang

文章推薦指數: 80 %
投票人數:10人

這個區段通常位於heap 或stack 之後,避免因heap 或stack 溢位而覆寫CPU ... heap 區段的記憶體空間用於儲存動態配置的變數,例如C 語言的 malloc ... Blogger舊站 關於 Facebook Flickr 物聯網 網站架設 程式設計 統計 素食 特價優惠 宗教 物聯網 網站架設 程式設計 統計 素食 特價優惠 宗教 C語言程式的記憶體配置概念教學 2017/03/01 4則留言 本篇介紹C語言程式的記憶體配置概念,並以實際的範例程式碼來說明。

在使用C語言開發比較低階的程式之前,多少都要了解一下程式實際在執行時的記憶體配置情況,以下我們以最簡單的實際範例來說明。

C語言程式記憶體配置概念 下圖為典型的C語言程式在執行時的記憶體配置圖,記憶體的使用主要可分為text、data、bss、stack、heap與system這幾個部分。

C語言程式記憶體配置(LibreOffice原始檔) 以下是各個區塊的說明。

text:程式碼 文字區段(textsegment)也稱為程式碼區段(codesegment),這裡存放的是可執行的CPU指令(instructions)。

這個區段通常位於heap或stack之後,避免因heap或stack溢位而覆寫CPU指令。

通常文字區段的資料是可以共用的,當多個同樣的程式在執行時,在記憶體中只需要存有一份就夠了,而這個文字區段通常都是唯讀的,避免程式本身誤改了自己的CPU指令。

data:初始化靜態變數 初始化資料區段(initializeddatasegment)儲存的是一些已經初始化的靜態變數,例如有經過初始化的C語言的全域變數(globalvariables)以及靜態變數(staticvariables)都是儲存於此處。

這個區段的變數又可分為唯讀區域(read-onlyarea)以及可讀寫區域(read-writearea),可讀寫區域用於存放一般變數,其資料會隨著程式的執行而改變,而唯讀區域則是存放固定的常數。

bss:未初始化靜態變數 未初始化資料區段(uninitializeddatasegment)又稱為bss區段(這個名稱的起源來自於古老的組譯器,代表blockstartedbysymbol)是儲存尚未被初始化的靜態變數,而這些變數在程式執行之前會被系統初始化為0或是null。

stack:區域變數 堆疊區段(stacksegment)用於儲存函數的區域變數,以及各種函數呼叫時需要儲存的資訊(例如函數返回的記憶體位址還有呼叫者函數的狀態等),每一次的函數呼叫就會在堆疊區段建立一個stackframe,儲存該次呼叫的所有變數與狀態,這樣一來同一個函數重複被呼叫時就會有不同的stackframe,不會互相干擾,遞迴函數就是透過這樣的機制來執行的。

heap:動態配置變數 heap區段的記憶體空間用於儲存動態配置的變數,例如C語言的malloc以及C++的new所建立的變數都是儲存於此。

堆疊區段一般的狀況會從高記憶體位址往低記憶體位址成長,而heap剛好從對面以相反的方向成長。

system:命令列參數與環境變數 system區段用於儲存一些命令列參數與環境變數,這部分會跟系統有關。

實際範例 這是一個最簡單的C語言程式: #include intmain(){ return0; } 編譯之後,可使用size查看它的內部記憶體配置: gccsource.c sizea.out text data bss dec hex filename 1099 544 8 1651 673 a.out 新增一個未初始化的全域靜態變數: #include doubleglobal[30];//儲存於bss的未初始化靜態變數 intmain(){ return0; } 查看內部記憶體配置: gccsource.c sizea.out text data bss dec hex filename 1099 544 272 1915 77b a.out 這一個未被初始化的陣列被放在bss區段。

接著增加一個已初始化的靜態變數: #include intmain(){ //儲存於data的已初始化靜態變數 staticintx[5]={1,2,3,4,5}; return0; } 查看內部記憶體配置: gccsource.c sizea.out text data bss dec hex filename 1099 564 4 1667 683 a.out 有初始化的靜態變數或全域變數都會被放進data區段中。

儲存於stack與heap的變數在這裡看不到,以下是儲存於各種區段的變數: #include constintglobal_x=1;//儲存於data區段(唯讀區域) intglobal_y=1;//儲存於data區段(可讀寫區域) intglobal_z;//儲存於bss區段 intmain(){ conststaticintx=1;//儲存於data區段(唯讀區域) staticinty=1;//儲存於data區段(可讀寫區域) staticintz;//儲存於bss區段 intw=1;//儲存於stack區段 //儲存於heap區段 char*buf=(char*)malloc(sizeof(char)*100); //... free(buf); return0; } 參考書籍: RandalE.BryantandDavidR.O’Hallaron.2010.ComputerSystems:AProgrammer’sPerspective(2nded.).Addison-WesleyPublishingCompany,USA. W.RichardStevensandStephenA.Rago.2013.AdvancedProgrammingintheUNIXEnvironment(3rded.).Addison-WesleyProfessional 參考資料:GeeksforGeeks、hackerearth、cs-Fundamentals.com、Codingfreak、ProProgramming 程式設計 C/C++ G.T.Wang 個人使用Linux經驗長達十餘年,樂於分享各種自由軟體技術與實作文章。

3留言 新增留言→ AnsonJiang 堆疊區段一般的狀況會從低記憶體位址往高記憶體位址成長,而heap剛好從對面以相反的方向成長。

2018/04/08 回覆 AnsonJiang 這句話和開頭的記憶體配置圖示不符合,請問哪一邊是正確的呢? 2018/04/08 回覆 G.T.Wang 抱歉,文字有誤,圖示是正確的。

已將錯誤文字修正,感謝。

2018/04/08 回覆 1則自動引用通知 計算機與網路入侵偵測0_Homework#1–10^-21 LeaveaReply取消回覆 留言* Name* Email* Website 搜尋 分類Arduino(5) BeagleBoneBlack(1) DIY(54) Linux(317) macOS(33) Octave(15) Perl(12) R(47) Windows(98) WordPress(16) 個人(15) 免費(35) 兒童(30) 實用工具(85) 手機(13) 技巧(45) 有趣(99) 樹莓派(57) 物聯網(55) 玄學(11) 生活(209) 程式設計(137) 統計學(8) 網頁空間(36) 網頁開發(128) 虛擬化(7) 農業(42) 遊戲(9) 開箱(132) 雲端(4) 宗教 如何戒邪淫、遠離婚外情 戒淫寶典:《壽康寶鑑》白話有聲書 公益 社團法人新竹縣愛心物資集發協會 家扶基金會 Yahoo奇摩公益 igiving公益網 台灣世界展望會 ©2022G.T.Wang



請為這篇文章評分?