經由過程一個小例子來簡略懂得C說話中的內存空間治理。本站提示廣大學習愛好者:(經由過程一個小例子來簡略懂得C說話中的內存空間治理)文章只能為提供參考,不一定能成為您想要的結果。以下是經由過程一個小例子來簡略懂得C說話中的內存空間治理正文
關於一個C說話法式而言,內存空間重要由五個部門構成代碼段(.text)、數據段(.data)、BSS段(.bss),堆和棧構成,個中代碼段,數據段和BSS段是編譯的時刻由編譯器分派的,而堆和 棧是法式運轉的時刻由體系分派的。結構以下
在上圖中,由編譯器分派的地址空間都是在銜接的時刻分派的,而運轉時分派的空間是在法式運轉時由體系分派的
BSS段:BSS段(bss segment)平日是指用來寄存法式中未初始化的全局變量和靜態變量 (這裡留意一個成績:普通的書上都邑說全局變量和靜態變量是會主動初始化的,那末哪來的未初始化的變量呢?變量的初始化可以分為顯示初始化和隱式初始化,全局變量和靜態變量假如法式員本身不初始化的話切實其實也會被初始化,那就是不論甚麼類型都初始化為0,這類沒有顯示初始化的就是我們這裡所說的未初始化。既然都是0那末就沒需要把每一個0都存儲起來,從而節儉磁盤空間,這是BSS的重要感化)的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分派。 BSS節不包括任何數據,只是簡略的保護開端和停止的地址,即總年夜小,以便內存區能在運轉時分派並被有用地清零。BSS節在運用法式的二進制映象文件中其實不存在,即不占用磁盤空間 而只在運轉的時刻占用內存空間 ,所以假如全局變量和靜態變量未初始化那末其可履行文件要小許多。
數據段:數據段(data segment)平日是指用來寄存法式中已初始化的全局變量和靜態變量的一塊內存區域。數據段屬於靜態內存分派,可以分為只讀數據段和讀寫數據段。 字符串常量等,但普通都是放在只讀數據段中 。
代碼段:代碼段(code segment/text segment)平日是指用來寄存法式履行代碼的一塊內存區域。這部門區域的年夜小在法式運轉前就曾經肯定,而且內存區域平日屬於只讀, 某些架構也許可代碼段為可寫,即許可修正法式。在代碼段中,也有能夠包括一些只讀的常數變量,例如字符串常量等,但普通都是放在只讀數據段中 。
堆(heap):堆是用於寄存過程運轉中主動態分派的內存段,它的年夜小其實不固定,可靜態擴大或縮減。當過程挪用malloc等函數分派內存時,新分派的內存就主動態添加到堆上(堆被擴大);當應用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
棧 (stack):棧又稱客棧, 是用戶寄存法式暫時創立的部分變量,也就是說我們函數括弧“{}”中界說的變量(但不包含static聲明的變量,static意味著在數據段中寄存變 量)。除此之外,在函數被挪用時,其參數也會被壓入提議挪用的過程棧中,而且待到挪用停止後,函數的前往值也會被寄存回棧中。因為棧的先輩先出特色,所以 棧特殊便利用來保留/恢復挪用現場。從這個意義上講,我們可以把客棧算作一個存放、交流暫時數據的內存區。留意:棧空間是向下增加的,每一個線程有一個本身的棧,在linux上默許的年夜小是8M,可以用ulimit檢查和修正。
棧體系供給的功效,特色是疾速高效,缺陷是無限制,數據不靈巧;而堆是函數庫供給的功效,特色是靈巧便利,數據順應面普遍,然則效力有必定下降。
以下是一個簡略的c文件,情況是OS--Linux,ARCH--PPC
##sta.c### #include <stdio.h> int kk[100] = {1,2,3,4,5}; int tt[100]; int ii; int main() { int i; static int si; char a[10]= "abcd"; printf("i is %d/n"); return 0; } 經由gcc -S sta.c以後,生成的匯編代碼以下 ##sta.s### .file "sta.c" .gnu_attribute 4, 2 .gnu_attribute 8, 3 .globl kk .section ".data" .align 2 .type kk, @object .size kk, 400 kk: .long 1 .long 2 .long 3 .long 4 .long 5 .zero 380 .lcomm si.2254,4,4 .type si.2254, @object .section .rodata .align 2 .LC1: .string "i is %d/n" .align 2 .LC0: .string "abcd" .zero 5 .section ".text" .align 2 .globl main .type main, @function main: stwu 1,-32(1) mflr 0 stw 0,36(1) stw 31,28(1) mr 31,1 lis 9,.LC0@ha la 9,.LC0@l(9) lwz 0,0(9) lbz 9,4(9) stw 0,12(31) stb 9,16(31) li 0,0 stb 0,17(31) li 0,0 stb 0,18(31) li 0,0 stb 0,19(31) li 0,0 stb 0,20(31) li 0,0 stb 0,21(31) lis 9,.LC1@ha la 3,.LC1@l(9) crxor 6,6,6 bl printf li 0,0 mr 3,0 lwz 11,0(1) lwz 0,4(11) mtlr 0 lwz 31,-4(11) mr 1,11 blr .size main, .-main .comm tt,400,4 .comm ii,4,4 .ident "GCC: (GNU) 4.2.3" .section .note.GNU-stack,"",@progbits
Note: 普通編譯器和操作體系完成來講,關於虛擬地址空間的最低(從0開端的幾K)的一段空間是未被映照的,也就是說它在過程空間中,但沒有付與物理地址,不克不及被拜訪。這也就是對空指針的拜訪會招致crash的緣由 ,由於空指針的地址是0。至於為何預留的不是一個字節而是幾K,是由於內存是分頁的,至多要一頁;別的幾k的空間還可以用來捕獲應用空指針的情形。