動態存儲區
1. 簡單說一說內存泄漏、內存溢出、內存碎片。
在內存中供用戶使用的內存區有三個:
程序存儲區、
靜態存儲區、
動態存儲區。
程序的數據一般存放在靜態存儲區螞明和動態存儲區。
靜態存儲區是當程序開始的時候就分配好的一塊固定的內存區。
動態存儲區一般是在程序運行過程中根據需要動態去分配和釋放的內存區域。這塊內存區域需要開發人員在使用完畢之後進行釋放,如果沒有釋放動態分配的內存區域就會造成內存泄漏。相應的這塊區域也不能夠被使用。
舉個例子:有一個可以裝50ml水的空杯子,但是你非得向這個被子裡面倒了100ml水,那麼這個時候多餘的水肯定會流出來,這就是水溢出了。那麼放到內存來講,就是內存溢出。
內存碎片分為外部碎片和內部碎片
外部碎片指的是還沒有被分配出去(不屬於任何進程)悶手告,但由於太小了無法分配給申請內存空間的新進程的內存空閑區域。
外部碎片是出於任何已分配區域或頁面外部的空閑存儲塊。這些存儲塊的總和可以滿足當前申請的長度要求,但是由於它們的地址不連續或其他原因,使得系統薯叢無法滿足當前申請。
內部碎片就是已經被分配出去(能明確指出屬於哪個進程)卻不能被利用的
空間;
內部碎片是處於內部或頁面內部的存儲塊。佔有這些區域或頁面的進程並不使用這個存儲塊。而在進程佔有這塊存儲塊時,系統無法利用它。直到進程釋放它,或進程結束時,系統才有可能利用這個存儲塊。
2. 動態存儲區與靜態存儲區的區別
我理解吧,這個動態跟靜態主要是針對指針而言的。而且對於單個變數來說,動態跟靜態的概念體現的不是特別清楚,下面主要介紹數組吧。
如果你聲明一個數組int a[100],那麼這個數組的大小就是100,在內存中的位置也固定,如果後來發現數組不夠大,你就只能重新定義一個更大的數組,而不能直接改變數組a的大小。這就是靜態存儲。
如果你聲明一個指針int *p,一開始你想開辟一個100的數組,就寫p = new int[100],後面發現100不夠大,你可以先delete []p,把原來的空間釋放掉,然後讓p = new int[200],p就會指向一個大小為200的數組,這個數組的大小以及在內存中的位置可以根據需要不斷變化。這就是動態存儲。
3. C語言中的動態內存分配的用法舉例
1、malloc函數:其作用是在內存的動態存儲區中分配一個長度為size的連續空間。其參數是一個無符號整形數,返回值是一個指向所分配的連續存儲域的起始地址的指針。
2、free函數:由於內存區域總是有限的,不能不限制地分配下去,而且一個程序要盡量節省資源,所以當所分配的內存區域不用時,就要釋放它,以便其它的變數或者程序使用。這時我們就要用到free函數。
3、calloc函數:其作用是在內存的動態存儲區中分配n個長度為 size 的連續空間。函數返回一個指向分配區域的起始位置的指針;如果分配不成功,則返回NULL。
(3)動態存儲區擴展閱讀:
函數運算符:
new
運算符new用於向系統申請動態存儲空間,並把首地址作為運算結果,它的使用形式為:
指針變數=new 數據類型;
例如:
int *p=new int
該語句的作用是會用new從內存中申請了一個int型變數(4個位元組),並將該變數的首地址賦給指針變數p。
new所建立的變數的初始值是任意的,也可在用new分配內存的同時進行初始化。使用形式為:
指針變數=new 數據類型(初始值)。
delete
堆內存可按照要求進行分配,程序對內存的需求量隨時會發生變化,有時程序在運行種可能會不再需要由new分配的內存空間,而且程序還未運行結束,這時就需要把先前佔用的內存空間釋放給堆內存,以後重新分配,供程序的其他部分使用。運算符delete用於釋放new分配的內存空間,刪除建立的對象,它的使用形式為:
delete指針變數;
其中的指針變數中保存著new分配的內存的首地址。
4. auto局部變數存儲在( )。(靜態存儲區、動態存儲區或寄存器)
程序的局部變數 全局變數 動態申請數據分別存儲在什麼地方?
量的類別:
根據作用域可分為全局變數和局部變數。
根據生存周期可分為靜態存儲方式和動態存儲方式,具體地又分為自動的(auto)、靜態的(static)、寄存器的(register)、外部的(extern)。
靜態存儲方式是指在程序運行期間分配固定的存儲空間的方式,動態存儲方式是在程序運行期間根據需要進行動態的分配存儲空間的方式。
每一個變數均有作用域和存儲類別兩個屬性,這些屬性共同用於描述一個變數,這些不同類型的變數與存儲位置的關系如下:
外部變數(全局變數)、靜態外部變數、靜態局部變數存儲在靜態存儲區。
自動局部變數(局部變數默認為自動局部變數)、函數形參存儲在動態存儲區,不論是靜態存儲區還是動態存儲區均屬於內存中的用戶區。
但是,寄存器變數是存儲在CPU寄存器中的而不是內存中。
首先說明一下與作用域相關的幾個屬性:
局部變數:在一個函數內部定義的變數是內部變數,它只在本函數范圍內有效,也就是說只有在本函數內才能使用它們,在此函數以外是不能使用這些變數的,這種類型的變數就稱為「局部變數」。
全局變數:在函數外定義的變數,可以為本源文件中其它函數所公用,有效范圍為從定義變數的位置開始到本源文件結束,這種類型的變數就稱為「全局變數」。
接下來說明一下與存儲類型相關的幾個屬性:
atuo:在聲明局部變數時,若不指定 static,默認均是 auto,這類變數都是動態分配存儲空間的,數據存儲在動態存儲區中。
static:在聲明局部變數時,使用關鍵字 static 將局部變數指定為「靜態局部變數」,這樣在函數調用結束後不消失而保留原值,即佔用的存儲單元不釋放,在下一次函數調用時,該變數已有值就是上次函數調用結束時的值。
register:在聲明動態局部變數或者函數形參時,可將變數聲明為register,這樣編譯系統就會為變數分配一個寄存器而不是內存空間,通過這種方式可提升對某些局部變數頻繁調用的程序的性能。(寄存器運算速度遠高於內存)
extern:用於擴展全局變數的作用域,比如如果函數想引用一個外部變數,但該外部變數在該函數後定義,那麼這個函數需要使用 extern 來聲明變數,這樣才能使用在該函數後面定義的全局變數。此外,extern 還可以在多文件的程序中聲明外部變數。
由於變數從不同維度劃分,形成了多種錯綜復雜的關系,在學習編程的時候需要重點關注。
5. 涓涓鍑芥暟鍐呴儴瀹氫箟鐨勫彉閲忕О涓猴紙錛夊畠瀛樻斁浜庯紙錛夊瓨鍌ㄥ尯錛屽湪鍑芥暟澶栭儴瀹氫箟鐨勫彉閲忕О涓猴紙錛夛紝瀹冨瓨鏀句簬錛堬級瀛樺偍鍖
涓涓鍑芥暟鍐呴儴瀹氫箟鐨勫彉閲忕О涓哄矓閮ㄥ彉閲忓嵆鍐呴儴鍙橀噺錛屽畠瀛樻斁浜庡姩鎬佸瓨鍌ㄥ尯錛屽湪鍑芥暟澶栭儴瀹氫箟鐨勫彉閲忕О涓哄栭儴鍙橀噺鍗鍏ㄥ矓鍙橀噺錛屽畠瀛樻斁浜庨潤鎬佸瓨鍌ㄥ尯銆
澶栭儴鍙橀噺涓哄湪鍑芥暟澶栭儴瀹氫箟鐨勫叏灞鍙橀噺錛屽畠鐨勪綔鐢ㄥ煙浠庡彉閲忕殑瀹氫箟澶勫紑濮嬶紝鍒版湰紼嬪簭鏂囦歡鐨勭粨灝俱傚湪姝や綔鐢ㄥ煙鍐咃紝鍏ㄥ矓鍙橀噺鍙涓哄悇涓鍑芥暟鎵寮曠敤銆傜紪璇戞椂灝嗗栭儴鍙橀噺鍒嗛厤鍦ㄩ潤鎬佸瓨鍌ㄥ尯銆
灞閮ㄥ彉閲忕殑浣滅敤鍩熶負瀹氫箟璇ュ彉閲忕殑鍑芥暟鎴栧畾涔夎ュ彉閲忕殑澶嶅悎璇鍙ャ傚矓閮ㄥ彉閲忕殑鐢熷瓨鏈熸槸浠庡嚱鏁拌璋冪敤鐨勬椂鍒葷畻璧峰埌鍑芥暟榪斿洖璋冪敤澶勭殑鏃跺埢緇撴潫銆
鎵╁睍璧勬枡
鍏ㄥ矓鍙橀噺浠庣▼搴忚繍琛岃搗鍗沖崰鎹鍐呭瓨錛屽湪紼嬪簭鏁翠釜榪愯岃繃紼嬩腑鍙闅忔椂璁塊棶錛岀▼搴忛鍑烘椂閲婃斁鍐呭瓨銆備笌涔嬪瑰簲鐨勫矓閮ㄥ彉閲忓湪榪涘叆璇鍙ュ潡鏃惰幏寰楀唴瀛橈紝浠呰兘鐢辮鍙ュ潡鍐呯殑璇鍙ヨ塊棶錛岄鍑鴻鍙ュ潡鏃墮噴鏀懼唴瀛橈紝涓嶅啀鏈夋晥銆
灞閮ㄥ彉閲忓畾涔夊悗涓嶄細鑷鍔ㄥ垵濮嬪寲錛岄櫎闈炵▼搴忓憳鎸囧畾鍒濆箋傚叏灞鍙橀噺鍦ㄧ▼搴忓憳涓嶆寚瀹氬垵鍊肩殑鎯呭喌涓嬭嚜鍔ㄥ垵濮嬪寲涓洪浂銆傚湪鍚屼竴婧愭枃浠朵腑錛屽厑璁稿叏灞鍙橀噺鍜屽矓閮ㄥ彉閲忓悓鍚嶃傚湪灞閮ㄥ彉閲忕殑浣滅敤鍩熷唴錛屽叏灞鍙橀噺涓嶈搗浣滅敤銆
鏈夋椂闇瑕佸湪鍏朵粬鏂囦歡涓浣跨敤extern鏉ュ0鏄庡叏灞鍙橀噺錛屼互鎵╁睍鍏ㄥ矓鍙橀噺鐨勪綔鐢ㄥ煙銆 涔熷彲鐢╯tatic澹版槑鍏ㄥ矓鍙橀噺錛屼嬌璇ュ彉閲忎笉鑳借鍏朵粬鏂囦歡寮曠敤銆傚湪B璇璦銆丆璇璦鍜屼竴浜涘叾瀹冩淳鐢熺殑璇璦錛堝侰++錛変腑錛屽栭儴鍙橀噺鍗沖栭儴鐨勫彉閲忋
鍙傝冭祫鏂欐潵婧愶細鐧懼害鐧劇-灞閮ㄥ彉閲
鍙傝冭祫鏂欐潵婧愶細鐧懼害鐧劇-澶栭儴鍙橀噺
6. 什麼是靜態存儲區和動態存儲區啊
1. 全局變數和靜態數據放在靜態存儲區,生命周期為從申請到程序退出。因此局部變數若定義為static,則存儲在靜態存儲區,否則存儲在函數的棧內,生命周期為本函數內。
2 動態存儲放自動變數和局部變數
7. 什麼數據存放在動態存儲區中
動態申請的數據存儲空間位於動態存儲區
對於C++是new,對於純C語言是malloc