《C語言深度刨析》整理 記憶體管理

2021-06-01 20:05:53 字數 3157 閱讀 9860

一、記憶體的儲存區

1.、棧(堆疊)區、堆區、靜態區等

(1)、棧區(堆疊)(stack):由編譯器自動分配釋放 ,存放函式引數值,區域性變數等。棧上的內容只在函式的範圍內存在,當函式執行結束,這些內容也會自動被毀.其特點是:效率高,但空間大小有限

(2)、堆區(heap) :一般由程式設計師分配釋放 , 由malloc 系列函式或new 操作符分配的記憶體。其生命週期由free 或delete 決定。在沒有釋放之前一直存在,直到程式結束,其特點是:使用靈活,空間比較大,但容易出錯

(3)、全域性區(靜態區):儲存自動全域性變數和static 變數(包括static 全域性和區域性變數),靜態區的內容在總個程式的生命週期內都存在,由編譯器在編譯的時候分配

(4)、文字常量區:常量字串就是放在這裡的。 程式結束後由系統釋放

(5)、程式**區:存放函式體的二進位制**。

二、c語言記憶體管理五條原則

【規則1】用malloc或new申請記憶體之後,應該立即檢查指標值是否為null。防止使用指標值為null的記憶體。

(很有可能申請連續一塊記憶體失敗)

【規則2】不要忘記為陣列和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。

【規則3】避免陣列或指標的下標越界,特別要當心發生「多1」或者「少1」操作。

【規則4】動態記憶體的申請與釋放必須配對,防止記憶體洩漏。 (比如malloc和free,new和delete)

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

三、常見的記憶體錯誤

1. 未給指標賦值,指標指向非法的值

(1)view plain

print?

#include "stdio.h"

#include "string.h"

struct

node  

nnode,*pnode;  

intmain()    

解析:

錯誤一:未給結構體申請記憶體空間,結構體指標pnode 指向非法記憶體導致程式異常

錯誤二:未給結構體中指向char 型別的指標name 分配記憶體,name指向非法記憶體導致程式異常

(2) 比較隱蔽指標未申請記憶體空間,指標指向非法的記憶體    

view plain

print?

#include "stdio.h"

#include "string.h"

#include "stdlib.h"

struct

node  

nnode, *pnode;  

intmain()    

解析:

表面看來程式為struct node 分配了記憶體,但是結構體中的指標char *name 未分配記憶體,指標name 的指向仍然是非法的

2. 沒有分配總夠的記憶體 

view plain

print?

#include "stdio.h"

#include "string.h"

#include "stdlib.h"

struct

node  

nnode,*pnode;  

intmain()    

解析:

(1). 誤將記憶體申請的大小 由sizeof(struct node)變成 sizeof(struct node *) 只申請了四個位元組的記憶體大

(2). 指標那麼也未申請記憶體位址

3. 為指標分配的記憶體太小

view plain

print?

char

*p1 = 「abcdefg」;  

char

*p2 = (

char

*)malloc(

sizeof

(char

)*strlen(p1));  

view plain

print?

strcpy(p2,p1);  

解析:指標p1所佔的記憶體大小是 8,而為p2 申請的記憶體是 7個

解決:char *p2  =  (char *)malloc(sizeof(char)*strlen(p1) + 1*sizeof(char));  

4. 記憶體分配成功,但並未初始化

(1) 指標的初始化

初始化為有效的值: char *p = (char *)malloc(sizeof(char));

初始化為null :       char *p = null;

注:一般第二種比較常用,第二種寫法也可以用來debug的時候檢測assert除錯;

(2) 陣列的初始化

定義的時候初始化:  int  number[20]  = ;

定義後初始化:        memset(a, 0, sizeof(number);

5. 記憶體越界

這種情況比較常見於,訪問陣列的時候,迴圈變數控制的越界

比如:  

view plain

print?

inta[10] = ;  

for(i = 0; i <= 10; i++)    

解析:

陣列變數越界了。陣列迴圈變數的邊界取值的原則一般是從0開始,採用半開半閉的結構,這樣程式的可讀性強

6. 指標已經釋放但是仍然被其他的**呼叫

通常有三種情況:

第一種:free(p)之後,繼續通過p 指標來訪問記憶體。解決的辦法就是給p 置null。

第二種:函式返回棧記憶體。這是初學者最容易犯的錯誤。比如在函式內部定義了乙個陣列,卻用return 語句返回指向該陣列的指標。         

第三種:記憶體使用太複雜,弄不清到底哪塊記憶體被釋放,哪塊沒有被釋放。解決的辦法是重新設計程式,改善物件之間的呼叫關係。

重溫C語言 讀C語言深度解刨有感

重溫c語言 讀c語言深度解刨有感 c基礎的溫習 可以這樣認為,很多語言都有c語言的影子。同樣除了組合語言,c語言是最靠近底層的語言。自我認為,程式設計師編寫程式或者設計架構的時候,一定得考慮程式執行的資源占用與釋放問題,畢竟絕大部分程式都是執行在作業系統上的。定義 如 int i 指編譯器建立乙個物...

C語言深度解剖筆記6之記憶體管理

什麼是野指標 定義指標變數的同時最好初始化為null,用完指標之後也將指標變數的值設定為null。也就是說除了在使用時,別的時間都把指標 栓 到0 位址處。這樣它就老實了。棧 堆和靜 我們可以簡單的理解為記憶體分為三個部分 靜態區,棧,堆。堆疊就是棧,靜態區 儲存自動全域性變數和static 變數 ...

c語言記憶體管理

在c語言中,根據資料在記憶體中存在的時間 生存期 不同,將記憶體空間分為三個區 1.程式區 用於儲存程式的 即程式的二進位制 存放函式體的二進位制 2.靜態儲存區 用於儲存全域性變數和靜態變數,這些變數的空間在程式編譯時就已經分配好了.全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態...