C C 記憶體管理

2021-09-21 16:32:56 字數 2734 閱讀 9519

靜態記憶體是指在程式開始執行時由編譯器分配的記憶體,它的分配是在程式開始編譯時完成的,不占用cpu資源。程式中的各種變數,在編譯時系統已經為其分配了所需的記憶體空間,當該變數在作用域內使用完畢時,系統會自動釋放所占用的記憶體空間。變數的分配與釋放,都無須程式設計師自行考慮。

eg:基本型別,陣列

使用者無法確定空間大小,或者空間太大,棧上無法分配時,會採用動態記憶體分配。用malloc或者new申請任意多少的記憶體,程式設計師自己負責在何時用free或者delete手動釋放記憶體。只用malloc或new分配的內存在堆裡。

(1) 靜態記憶體分配在編譯時完成,不占用cpu資源; 動態記憶體分配在執行時,分配與釋放都占用cpu資源。

(2) 靜態內存在棧(stack)上分配; 動態記憶體在堆(heap)上分配。

(3) 動態記憶體分配需要指標和引用型別支援,靜態不需要。

(4) 靜態記憶體分配是按計畫分配,由編譯器負責; 動態記憶體分配是按需分配,由程式設計師負責。

虛擬記憶體結構:

記憶體分配方式一共有三種:

(1)從靜態儲存

區域分配(全域性變數,靜態變數,在虛擬記憶體的資料段

)內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在,例如,全域性變數,靜態變數。

(2)在棧上建立(區域性變數,在虛擬記憶體的棧,屬於靜態記憶體

)在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束後這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。

(3)在堆上分配,亦稱動態記憶體分配(malloc或者new申請,在虛擬記憶體的

堆裡,即在「空洞」裡,屬於動態記憶體)

程式在執行的時候用malloc或者new申請任意多少的記憶體,程式設計師自己負責在何時用free或者delete手動釋放記憶體。動態記憶體的生存期由程式設計師決定,使用非常靈活,但是問題也多。

(1)靜態儲存區域以及建立的棧,在函式執行完以後,出棧銷毀,這個過程會自動釋放靜態分配的記憶體,不需要程式設計師手動操作;

(2)而動態分配的記憶體,實際是在堆上,系統沒法自動釋放堆上的記憶體,需要程式設計師手動寫free或者delete函式來告訴系統需要釋放堆上哪個位置的記憶體;

(1)記憶體尚未分配成功,卻使用了它;

解決辦法:在使用記憶體之前檢查指標是否為null。如果指標p是函式的引數,那麼在函式的入口使用assert(p != null) 進行檢查,如果是用malloc或者new來申請的,應該用if (p == null)或者 if (p != null) 來進行防錯處理。

(2)記憶體分配雖然成功,但是尚未初始化就引用它;

錯誤原因:一是沒有初始化的觀念,二是誤以為記憶體的預設初值全為零,導致引用初值錯誤(如陣列)。

解決辦法:記憶體的預設初值是什麼並沒有統一的標準,儘管有些時候為零值,但是寧可信其有,不可信其無,無論以何種方式建立陣列,都要賦初值。

int *p1,*p2;

int a=100,b=60;

p1=&a;

p2=&b;

//或者*p1=a;*p2=b;

printf("%d,%d\n",*p1,*p2);//100,60

(3)記憶體分配成功並初始化,但是超過了記憶體的邊界;

這種問題常出現在陣列越界,寫程式是要仔細。

(4)忘記釋放記憶體,造成記憶體洩露;

含有這種錯誤的函式每次被呼叫都會丟失一塊記憶體,開始時記憶體充足,看不到錯誤,但終有一次程式死掉,報告記憶體耗盡。

(1)用malloc 或者 new 申請記憶體之後,應該立即檢查指標值是否為 null ,防止使用指標值為null的記憶體;

(2)不要忘記陣列和動態記憶體賦初值,防止未被初始化的記憶體作為右值使用;

(3)避免陣列或者指標下標越界,特別要當心「多1」或者「少1」的操作;

(4)動態記憶體的申請與釋放必須配對,防止記憶體洩露;

(5)用free或者delete釋放了記憶體之後,立即將指標設定為null,防止產生「野指標」。

8.1動態記憶體分配

//函式說明

#includevoid *malloc(size_t size);

void *calloc(size_t nmemb,size_t size);

(1)malloc的引數size表示分配的記憶體空間的大小,單位是位元組byte。

(2)calloc的引數nmemb表示分配的記憶體空間佔的資料項數目,引數size表示乙個資料項的大小,單位是位元組byte。也就是說calloc分配的是nmemb x size大小的記憶體空間。

兩者的區別是calloc將初始化所分配的記憶體空間,把所有位設定為0。

(3)呼叫成功返回分配記憶體的位址,失敗返回null。

8.2動態記憶體釋放

//函式說明

#includevoid free(void *ptr);

動態記憶體示例:

#include#includechar *upcase(char *inputstring);

int main(void)

//子函式中動態分配的記憶體的指標返回到主函式中

char *upcase(char *inputstring)

strcpy(newstring,inputsreing);

for(counter=0;counter=97 && newstring[counter]<=122)

}  return newstring;

}

c c 記憶體管理

我一直覺得記憶體是很複雜的東西.也許我把這篇文章完成的時候,我會了解一點c 的記憶體管理機制 從硬體開始 記憶體器位址空間 匯流排位址空間 cpu位址空間 虛擬記憶體位址空間 程式位址空間 邏輯位址空間 程式位址空間對c 程式設計師來說是可見的,其他位址空間我們並不關心 通過列印pointer的值 ...

C C 記憶體管理

寫乙個好的c 程式,我們要懂得好多東西,比如說最基本的物件導向程式設計思想,c 的封裝 繼承 多型機制,設計模式等,還有乙個很重要的內容便是效能優化,像c c 這種接近底層的語言,追求的就是效能,與之相關的一項內容便是記憶體管理,記憶體分配要合理,禁止破壞記憶體,不能有記憶體洩漏,操作不好的話,程式...

C C 記憶體管理

1.相同點 失敗 null 2 使用之前都要進行判斷是否為空 3 釋放空間的方式 free 4 返回值 void 可以強制型別轉換 2.不同點 1 malloc 引數 位元組數 功能 負責將空間給出 2 calloc 引數 單個元素位元組數,元素個數 功能 給出空間,且對空間進行初始化為0 若p為n...