1. 程式人生 > >C語言記憶體空間分佈詳解

C語言記憶體空間分佈詳解

BSS段:(bss segment)通常是指用來存放程式中未初始化全域性變數的一塊記憶體區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態記憶體分配。

資料段:資料段(data segment)通常是指用來存放程式中已初始化全域性變數的一塊記憶體區域。資料段屬於靜態記憶體分配。
程式碼段: 程式碼段(code segment/text segment)通常是指用來存放程式執行程式碼的一塊記憶體區域。這部分割槽域的程式碼屬於只讀。在程式碼段中,字串常量也屬於這部分。 堆(heap):堆是用於存放程序執行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減
棧(stack):棧又稱堆疊,存放程式的區域性變數除此以外,在函式被呼叫時,棧用來傳遞引數和返回值等。由於棧的先進先出特點,所以棧特別方便用來儲存/恢復呼叫現場 下面圖來自UNIX環境高階程式設計書中:


左邊是UNIX/LINUX系統下可執行檔案內部的組織結構,右邊是可執行檔案對應到程序邏輯地址空間(即記憶體)的劃分情況。


首先是堆疊區(stack),堆疊是由編譯器自動分配釋放,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。棧的申請是由系統自動分配,如在函式內部申請一個區域性變數 int h,同時判別所申請空間是否小於棧的剩餘空間,如若小於的話,在堆疊中為其開闢空間,為程式提供記憶體,否則將報異常提示棧溢位。   


其次是堆(heap),堆一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。堆的申請是由程式設計師自己來操作的,在C中使用malloc函式,而C++中使用new運算子,但是堆的申請過程比較複雜:當系統收到程式的申請時,會遍歷記錄空閒記憶體地址的連結串列,以求尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點連結串列中刪除,並將該結點的空間分配給程式,此處應該注意的是有些情況下,新申請的記憶體塊的首地址記錄本次分配的記憶體塊大小,這樣在delete尤其是 delete[]時就能正確的釋放記憶體空間。

接著是全域性資料區(靜態區) (static),全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。另外文字常量區,常量字串就是放在這裡,程式結束後有系統釋放。


最後是程式程式碼區,放著函式體的二進位制程式碼。

舉例說明一下:
int a = 0;                   //全域性初始化區
char *p1;                //全域性未初始化區


int main()
{
        int b;                // 棧
        char s[] = "abc";       //棧
        char *p2;             //棧
        char *p3 = "123456";    //123456\0在常量區,而p3在棧上

        static int c =0;    //全域性(靜態)初始化區

        p1 = (char *)malloc(10);

        p2 = (char *)malloc(20); //分配得來得10和20位元組的區域就在堆區

        strcpy(p1, "123456");    //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。

        return 0;
}

1、程序地址空間

一個程序一旦建立,就會自認為佔有4G記憶體(X86_32),這個記憶體被稱作虛擬記憶體,也就是程序的地址空間。在Linux下,程序地址空間的佈局大致如下圖所示,其中的使用者空間大致由這些部分組成:

  1. 程式碼段
  2. 初始化資料段
  3. 未初始化資料段

這些段,反映到ELF格式的目標檔案(object file)中,就又可能由許多不同的節(section)組成。

相關推薦

C語言記憶體空間分佈

BSS段:(bss segment)通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態記憶體分配。 資料段:資料段(data segment)通常是指用來存放程式中已初始化的全域性

C語言記憶體管理超

補充: 1.一個正在執行著的C編譯程式佔用的記憶體分為棧區、堆區、未初始化資料區(BBS)、初始化資料區、程式碼區5個部分。 (1)棧區:存放函式的引數值、區域性變數的值。由編譯器自動分配釋放。 (2)堆區:用於動態記憶體分配。由使用者通過malloc或new函式分配,由使

【轉】 C語言文件操作

pri void rfi 識別 archive format 隨機 stat 文本文 轉自:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551780.html C語言中沒有輸入輸出語句,所有的輸入輸出功能都用

C語言do while迴圈

do…while 迴圈不經常使用,其主要用於人機互動。它的格式是: do { 語句; } while (表示式); 注意,while 後面的分號千萬不能省略。 do…while 和 while 的執行過程非常相似,唯一的區別是:“do…while 是先執行一次迴圈體,然後再判別表示式

C語言的結構體(轉載只是為了查閱方便,若有侵權立刪)

C語言的結構體詳解 結構體(struct) 1、定義   一般格式為:          struct 結構名          {    

嵌入式C語言之位操作

1.位操作符:     位操作直接將兩個運算元按照二進位制對應進行操作;     例:0xaa&(位與)0xf0=0xa0;     邏輯操作是  兩個運算元整體來操作;     例

結構體指標,C語言結構體指標

結構體指標,可細分為指向結構體變數的指標和指向結構體陣列的指標。 指向結構體變數的指標 前面我們通過“結構體變數名.成員名”的方式引用結構體變數中的成員,除了這種方法之外還可以使用指標。前面講過,&student1 表示結構體變數 student1 的首地址,即 student1 第一個項的地址

C語言正則表示式

標準的C和C++都不支援正則表示式,但有一些函式庫可以輔助C/C++程式設計師完成這一功能,其中最著名的當數Philip Hazel的Perl-Compatible Regular Expression庫,許多Linux發行版本都帶有這個函式庫。   C語言處理正則表示式常用的函

linux中C語言標頭檔案

linux中C程式標頭檔案的種類 一類:#include<stdio.h> stdio.h檔案就在/usr/include目錄下 二類:#include<arpa/inet.h> arpa/是/usr/include目錄下的子目錄,inet.h其實是/usr/include

C語言專案的建立

最近為方便記錄我的IT學習生活和相關經驗,於是將有關自己對對相關知識的見解置於CSDN部落格上,以供各位學習交流。 今天我要分享的主題是有關C語言專案的建立和相關基礎知識,下面就以VS編譯器為例進行相關講解,若是有不當之處,還希望各位博友諒解並指出。 VS中

C語言for語句用法

在C語言中,for語句使用最為靈活,它完全可以取代 while 語句。它的一般形式為: for(表示式1; 表示式2; 表示式3) 語句 它的執行過程如下:先求解表示式1。 求解表示式2,若其值為真(非0),則執行for語句中指定的內嵌語句,然後執行下面第3)步;若其值

C語言預處理命令

本文參考諸多資料,詳細介紹常用的幾種預處理功能。因成文較早,資料來源大多已不可考證,敬請諒解。全文字數2萬,閱讀時間50分鐘,建議先收藏。 一 前言 預處理(或稱預編譯)是指在進行編譯的第一遍掃描(詞法掃描和語法分析)之前所作的工作。預處理指令指示在程式正式編譯前就由編譯器進行的操作

C語言之#include用法

學習Linux C,必須要理解include,只要弄清以下幾個問題,就能完全理解include了! 1.#include 實質是什麼? 預編譯的時候copy include標頭檔案的內容到當前行 (疑問:預編譯命令 $gcc -E test.c -o test.i) 2.

C語言編譯過程總結

本來打算把編譯部分的內容總結一下,偶然看到一位網友的文章寫得很全面,故此稍加整理,以作備忘。        C語言的編譯連結過程要把我們編寫的一個c程式(原始碼)轉換成可以在硬體上執行的程式(可執行程式碼),需要進行編譯和連結。編譯就是把文字形式原始碼翻譯為機器語言形式的目

C語言,檔案操作

在 C 語言中,檔案操作的函式大多包含在 標頭檔案中,使用時記得 #include。 一、開啟和關閉檔案 1. 開啟檔案 FILE * fopen ( const char * filename, const char * mode ); 開啟一個檔案,成功則返回

C語言標頭檔案

1. GCC編譯時問題 在由多個C語言檔案組成的程式中,對於標頭檔案的管理非常重要。標頭檔案提供給使用者一個介面,使用者從中可以知道可以呼叫哪些函式,實現哪些功能,而不必去管這些功能的具體實現。因此,寫好標頭檔案是非常關鍵的。在標頭檔案中,最常見的問題是"標頭檔案的重複包含"。其意思是同一標頭

c語言檔案操作函式

C語言中沒有輸入輸出語句,所有的輸入輸出功能都用 ANSI C提供的一組標準庫函式來實現。檔案操作標準庫函式有:       檔案的開啟操作 fopen 開啟一個檔案       檔案的關閉操作 fclose 關閉一個檔案       檔案的讀寫操作 fgetc 從檔案中讀取一個字元            

C語言陣列與指標

好多同學都說:“老師,我看到指標就暈!”,說實話,見過暈血的,見過暈車的,暈指標的到是第一次聽說!        我們先來分析一下暈車的原理,再來對比一下為什麼暈指標。        暈車,是因為耳朵裡的一個器官對外界的振動太敏感,導致身體調節功能紊亂,系統不能正常工作

C語言貪吃蛇()——連結串列實現

貪吃蛇設計思路:螢幕座標:拓展功能:1.F1,F2控制加速減速  空格暫停遊戲  Esc退出2.加速每個食物得分更高先打印出遊戲介面,還有初始化蛇,蛇的節點用字串★表示,遊戲背景用■表示,因為這些字串佔兩個位元組的寬度,所以每次x,y座標的對應關係是x=y*2。在相應位置打印

菜鳥學習-C語言函式引數傳遞-結構體與陣列

C語言中結構體作為函式引數,有兩種方式:傳值和傳址。 1.傳值時結構體引數會被拷貝一份,在函式體內修改結構體引數成員的值實際上是修改呼叫引數的一個臨時拷貝的成員的值,這不會影響到呼叫引數。在這種情況下,涉及到結構體引數的拷貝,程式空間及時間效率都會受到影