0.目錄
- 內存構成
- 內存分配
1.內存構成
C的內存基本上分為4部分:靜態(tài)存儲區(qū)夕玩、堆區(qū)你弦、棧區(qū)以及常量區(qū)。
- 棧
- 由編譯器自動分配釋放
- 函數(shù)體中定義的變量通常是在棧上
- 堆
- 一般由程序員分配釋放燎孟,若程序員不釋放禽作,程序結束時可能由OS回收
- 用malloc, calloc, realloc等分配內存的函數(shù)分配得到的就是在堆上
- 全局區(qū)(靜態(tài)區(qū))
- 全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域揩页,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域(C++中已經不再這樣劃分)旷偿,程序結束釋放;
- 在所有函數(shù)體外定義的是全局量
- 加了static修飾符后不管在哪里都存放在全局區(qū)
- 常量區(qū)
- 專門放常量的地方爆侣,程序結束釋放
- 函數(shù)中的"adgfdf"這樣的字符串存放在常量區(qū)
在C++中內存分成5個區(qū)萍程,分別是堆、棧兔仰、全局/靜態(tài)存儲區(qū)茫负、常量存儲區(qū)和代碼區(qū);
- 棧(stack)
就是那些由編譯器在需要的時候分配乎赴,在不需要的時候自動清楚的變量的存儲區(qū)忍法,里面的變量通常是局部變量潮尝、函數(shù)參數(shù)等和二。 - 堆(heap)
就是那些由new分配的內存塊绑洛,他們的釋放編譯器不去管,由我們的應用程序去控制功蜓,一般一個new就要對應一個delete嗤堰。如果程序員沒有釋放掉戴质,那么在程序結束后度宦,操作系統(tǒng)會自動回收踢匣。 - 全局/靜態(tài)存儲區(qū)(.bss段和.data段)
全局變量和靜態(tài)變量被分配到同一塊內存中,在以前的C語言中戈抄,全局變量又分為初始化的和未初始化的离唬,在C++里面沒有這個區(qū)分了,他們共同占用同一塊內存區(qū)划鸽。 - 常量存儲區(qū)(.rodata段)
這是一塊比較特殊的存儲區(qū)输莺,他們里面存放的是常量,不允許修改(當然裸诽,你要通過非正當手段也可以修改)嫂用。 - 代碼區(qū) (.text段)
存放代碼(如函數(shù)),不允許修改(類似常量存儲區(qū))丈冬,但可以執(zhí)行(不同于常量存儲區(qū))嘱函。
根據c/c++對象生命周期不同,c/c++的內存模型有三種不同的內存區(qū)域埂蕊,即:自由存儲區(qū)往弓,動態(tài)區(qū)、靜態(tài)區(qū)蓄氧。
- 自由存儲區(qū):局部非靜態(tài)變量的存儲區(qū)域函似,即平常所說的棧;
- 動態(tài)區(qū): 用new 喉童,malloc分配的內存撇寞,即平常所說的堆;
- 靜態(tài)區(qū):全局變量堂氯,靜態(tài)變量重抖,字符串常量存在的位置;
注:代碼雖然占內存祖灰,但不屬于c/c++內存模型的一部分钟沛;
在linux系統(tǒng)中,程序在內存中的分布如下所示:
低地址
.text---> .data --->.bss
--->heap(堆) --> unused <-- stack(棧)
-->env
高地址
其中 :
- .text 部分是編譯后程序的主體局扶,也就是程序的機器指令恨统。
- .data 和 .bss 保存了程序的全局變量叁扫,.data保存有初始化的全局變量,.bss保存只有聲明沒有初始化的全局變量畜埋。
- heap(堆)中保存程序中動態(tài)分配的內存莫绣,比如C的malloc申請的內存,或者C++中new申請的內存悠鞍。堆向高地址方向增長对室。
- stack(棧)用來進行函數(shù)調用,保存函數(shù)參數(shù)咖祭,臨時變量掩宜,返回地址等。
BSS 是“Block Started by Symbol”的縮寫么翰,意為“以符號開始的塊”牺汤。BSS是Unix鏈接器產生的未初始化數(shù)據段。其他的段分別是包含程序代碼的 “text”段和包含已初始化數(shù)據的“data”段浩嫌。BSS段的變量只有名稱和大小卻沒有值檐迟。此名后來被許多文件格式使用,包括PE码耐∽烦伲“以符號開始的塊” 指的是編譯器處理未初始化數(shù)據的地方。BSS節(jié)不包含任何數(shù)據骚腥,只是簡單的維護開始和結束的地址敦间,以便內存區(qū)能在運行時被有效地清零。BSS節(jié)在應用程序 的二進制映象文件中并不存在桦沉。
在采用段式內存管理的架構中(比如intel的80x86系統(tǒng))每瞒,bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區(qū)域,一般在初始化時bss 段部分將會清零纯露。bss段屬于靜態(tài)內存分配剿骨,即程序一開始就將其清零了。
比如埠褪,在C語言之類的程序編譯完成之后浓利,已初始化的全局變量保存在.data 段中,未初始化的全局變量保存在.bss 段中钞速。
2.內存分配
2.1 malloc
void *malloc(unsigned int size)
在內存的動態(tài)分配區(qū)域中分配一個長度為size的連續(xù)空間贷掖,如果分配成功,則返回所分配內存空間的首地址渴语,否則返回NULL苹威,申請的內存不會進行初始化。
2.2 calloc
void *calloc(unsigned int num, unsigned int size)
按照所給的數(shù)據個數(shù)和數(shù)據類型所占字節(jié)數(shù)驾凶,分配一個 num * size 連續(xù)的空間牙甫,calloc申請內存空間后掷酗,會自動初始化內存空間為0。
2.3 realloc
void *realloc(void *ptr, unsigned int size)
動態(tài)分配一個長度為size的內存空間窟哺,并把內存空間的首地址賦值給ptr泻轰,把ptr內存空間調整為size,申請的內存空間不會進行初始化且轨。
2.4 new
動態(tài)分配內存的運算符浮声,自動計算需要分配的空間,在分配類類型的內存空間時旋奢,同時調用類的構造函數(shù)泳挥,對內存空間進行初始化,即完成類的初始化工作黄绩。動態(tài)分配內置類型是否自動初始化取決于變量定義的位置羡洁,在函數(shù)體外定義的變量都初始化為0玷过,在函數(shù)體內定義的內置類型變量都不進行初始化爽丹。
new[]要求元素對象的類型必須具有默認構造函數(shù)(內建類型的“默認構造函數(shù)”是什么也不做),否則將不能使用new[]辛蚊。
2.5 new與malloc
- new是運算符粤蝎,malloc()是一個庫函數(shù);
- new會調用構造函數(shù)袋马,malloc不會初澎;
- new返回指定類型指針,malloc返回void*指針虑凛,需要強制類型轉換碑宴;
- new會自動計算需分配的空間,malloc不行桑谍;
- new可以被重載延柠,malloc不能。
2.6 delete
- delete會調用對象的析構函數(shù),和new對應
- delete是C++的運算符
- 對于內建簡單數(shù)據類型锣披,delete和delete[]功能是相同的贞间。對于自定義的復雜數(shù)據類型,delete和delete[]不能互用雹仿。delete[]刪除一個數(shù)組增热,delete刪除一個指針