內存是計算機的敏感資源,熟練掌握對內存的操做是一個優秀程序員必備的素質,
可是不少人對於如何對代碼和代碼數據中的數據分配很困惑,由此我查看了linux_c程序設計大全這本書 和一邊博客文章。
首先對於數據的內部存儲,衆所周知,不一樣的數據類型所佔用的空間是不一樣的。好比char 是一個byte,int是4個bytes等等。另外還需只要的是小端存儲和大端存儲。所謂小端存儲是數據的最低位存儲在內存中的低地址處,大端則相反。舉個例子,int a=0x12345678.這個是4個字節吧,那麼從內存的低地址開始存的是78這一個字節,而後是‘56’這個字節,最高一個字節是‘12’.因爲沒有圖,只能這麼說,地址(高到低),那麼存儲的是:12 34 56 78(記住內存存儲單位是一個字節)。
下面是:
可執行文件(包括 exe, dll)使用的格式叫 PE 格式,這種格式把內容按區段進行存儲,用一些 PE 工具就能夠查看這些區段,每一個區段除了大小,內容外還有一個屬性,表示是否可讀,可寫,可執行,可共享等等.經常使用的區段包括:
.text 代碼段
.data 數據段
.rdata 只讀數據段
.bss 未初始化數據段
.rc 資源段 等等。linux
Window 啓動進程的時候基本上會按照原樣把這些區段映射到內存中,咱們姑且把這部份內存叫作靜態內存吧。程序員
而後系統會啓動主線程,主線程可能再去啓動其餘線程,每個線程啓動的時候系統都會爲這個線程分配一塊內存,用於在這個線程中執行 push, pop 這些指令。這塊內存就是棧內存。另外程序在運行的過程當中還能夠隨時向系統申請內存,雖然方式有多種,可是最多見的是經過 HeapAlloc 來分配的,這種內存稱爲堆內存。這三種是最主要的,其它的內存好比還有線程局部存儲區 TLS,共享內存,託管內存,顯存等等,這裏就無論了。
C++ 使用的內存最終都會對應到上邊的去,首先全局變量和靜態變量會被編譯到 PE 文件中的 .data 數據段,通常編譯器會自動初始化爲 0, 將其寫入bss段,前提是你沒有初始化,好比int max ;定義了全局變量,可是沒有初始化,是不會寫入data數據段的,再好比int max={0},也是同一個道理。web
字符串常量會被編譯到只讀數據段中,這也是 char* x="hello"; x[0] = 'e'; 會出錯的緣由,由於 "hello" 這塊內存是隻讀的。可是通常來講定義 const 並不會使你的變量就分配到只讀數據段中去的。app
函數內定義的非靜態變量,函數參數都是程序執行到函數這裏來了後臨時在棧中留一塊區域出來,完了就收回的。
最後 new 的內存很明顯屬於堆內存。tcp
通常而言,計算機程序由代碼和數據組成,這兩個部分是影響程序所須要內存的重要因素。代碼是程序運行的指令,數據則是代碼要處理的對象,下面重點討論一下:函數
一個程序佔有的內存分爲5類:工具
1. 全局/靜態數據區---->對應 .data數據段oop
2.常量數據區--> .rdata只讀數據段post
3.代碼區---> .text代碼段 (存儲代碼)url
4.棧
5.堆
內存存儲狀況:
1. 全局/靜態數據區---> 全局/靜態數據
2.常量數據區(.rdata)-->常量字符串
3.棧---->自動變量或者局部變量,以及傳遞的函數參數
4.堆--->用戶控制 new/malloc出來的內存,注意內存泄露問題
下面經過具體代碼查看數據的存儲問題:
- #include <stdio.h>
- #include <stdlib.h>
- int nGlobal = 200;
- int main()
- {
- char *pLocalString1 = "LocalString1";
- const char *pLocalString2 = "LocalString2";
- static int nLocalStatic = 100;
- int nLocal = 1;
- const int nLocalConst = 20;
- int * pNew = (int *)malloc(sizeof(int)*5);;
- char *pMalloc = (char *)malloc(1);
- //全局/靜態數據區
- printf("全局/靜態數據區:/n");
- printf("global variable: 0x%x/n", &nGlobal);
- printf("static variable: 0x%x/n/n", &nLocalStatic);
- //常量區
- printf("常量區:/n");
- printf("pLocalString1 variable: 0x%x/n", pLocalString1);
- printf("pLocalString2 variable: 0x%x/n", pLocalString2);
- printf("nLocalConst variable: 0x%x/n/n", nLocalConst);
- //堆
- printf("堆:/n");
- printf("new variable: 0x%x/n", pNew);
- printf("malloc variable: 0x%x/n/n", pMalloc);
- //棧
- printf("棧:/n");
- printf("pointer pnew variable: 0x%x/n", &pNew);
- printf("pointer malloc variable: 0x%x/n", &pMalloc);
- printf("nLocal variable: 0x%x/n", &nLocal);
- printf("pointer pLocalString1 variable: 0x%x/n", &pLocalString1);
- printf("pointer pLocalString2 variable: 0x%x/n", &pLocalString2);
- printf("nLocalConst variable: 0x%x/n/n", &nLocalConst);
- return 0;
- }
下面是運行結果:
咱們能夠看到棧和堆的內存都存在內存對齊的。 堆的內存是按照34個字節對齊(個人機器是這樣的)的。
下面是各個數據所在區間的對應關係: