C記憶體管理詳解

2021-08-29 05:12:22 字數 3036 閱讀 5687

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

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

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

【規則4】動態記憶體的申請與釋放必須配對,防止記憶體洩漏。

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

陣列與指標區別:

陣列要麼在靜態儲存區被建立(如全域性陣列),要麼在棧上被建立。陣列名對應著(而不是指向)一塊記憶體,其位址與容量在生命期內保持不變,只有陣列的內容可以改變。

指標可以隨時指向任意型別的記憶體塊,它的特徵是「可變」,所以我們常用指標來操作動態記憶體。指標遠比陣列靈活,但也更危險。

內容複製與比較

不能對陣列名進行直接複製與比較。示例7-3-2中,若想把陣列a的內容複製給陣列b,不能用語句 b = a ,否則將產生編譯錯誤。應該用標準庫函式strcpy進行複製。同理,比較b和a的內容是否相同,不能用if(b==a) 來判斷,應該用標準庫函式strcmp進行比較。

語句p = a 並不能把a的內容複製指標p,而是把a的位址賦給了p。要想複製a的內容,可以先用庫函式malloc為p申請一塊容量為strlen(a)+1個字元的記憶體,再用strcpy進行字串複製。同理,語句if(p==a) 比較的不是內容而是位址,應該用庫函式strcmp來比較。

c**

// 陣列…  

char a = "hello";  

char b[10];  

strcpy(b, a); // 不能用 b = a;  

if(strcmp(b, a) == 0) // 不能用 if (b == a)  

…  

// 指標…  

int len = strlen(a);  

char *p = (char *)malloc(sizeof(char)*(len+1));  

strcpy(p,a); // 不要用 p = a;  

if(strcmp(p, a) == 0) // 不要用 if (p == a)  

…  

// 陣列…

char a = "hello";

char b[10];

strcpy(b, a); // 不能用 b = a;

if(strcmp(b, a) == 0) // 不能用 if (b == a)

…// 指標…

int len = strlen(a);

char *p = (char *)malloc(sizeof(char)*(len+1));

strcpy(p,a); // 不要用 p = a;

if(strcmp(p, a) == 0) // 不要用 if (p == a)

… malloc/free 的使用要點

函式malloc的原型如下:

void * malloc(size_t size);

用malloc申請一塊長度為length的整數型別的記憶體,程式如下:

int *p = (int *) malloc(sizeof(int) * length);

我們應當把注意力集中在兩個要素上:「型別轉換」和「sizeof」。

* malloc返回值的型別是void *,所以在呼叫malloc時要顯式地進行型別轉換,將void * 轉換成所需要的指標型別。

* malloc函式本身並不識別要申請的記憶體是什麼型別,它只關心記憶體的總位元組數。我們通常記不住int, float等資料型別的變數的確切位元組數。例如int變數在16位系統下是2個位元組,在32位下是4個位元組;而float變數在16位系統下是4個位元組,在32位下也是4個位元組。

在malloc的「()」中使用sizeof運算子是良好的風格,但要當心有時我們會昏了頭,寫出 p = malloc(sizeof(p))這樣的程式來。

* 函式free的原型如下:

void free( void * memblock );

為什麼free函式不象malloc函式那樣複雜呢?這是因為指標p的型別以及它所指的記憶體的容量事先都是知道的,語句free(p)能正確地釋放記憶體。如果p是null指標,那麼free對p無論操作多少次都不會出問題。如果p不是null指標,那麼free對p連續操作兩次就會導致程式執行錯誤。

new/delete 的使用要點

運算子new使用起來要比函式malloc簡單得多,例如:

int *p1 = (int *)malloc(sizeof(int) * length);

int *p2 = new int[length];

這是因為new內建了sizeof、型別轉換和型別安全檢查功能。對於非內部資料型別的物件而言,new在建立動態物件的同時完成了初始化工作。如果物件有多個建構函式,那麼new的語句也可以有多種形式。

typedef的用法

在c/c++語言中,typedef常用來定義乙個識別符號及關鍵字的別名,它是語言編譯過程的一部分,但它並不實際分配記憶體空間,例項像:

typedef    int       int;

typedef    int       array[10];

typedef   (int*)   pint;

、#define的用法

#define為一巨集定義語句,通常用它來定義常量(包括無參量與帶參量),以及用來實現那些「表面似和善、背後一長串」的巨集,它本身並不在編

譯過程中進行,而是在這之前(預處理過程)就已經完成了,但也因此難以發現潛在的錯誤及其它**維護問題,它的例項像:

#define   int             int

#define   true         1

#define   add(a,b)     ((a)+(b));

#define   loop_10    for (int i=0; i<10; i++)

#define

int int這樣的語句,用typedef一樣可以完成,用哪個好呢?我主張用typedef.

C 記憶體管理詳解

偉大的bill gates 曾經失言 640k ought to be enough for everybody bill gates 1981 程式設計師們經常編寫記憶體管理程式,往往提心吊膽。如果不想觸雷,唯一的解決辦法就是發現所有潛伏的地雷並且排除它們,躲是躲不了的。本文的內容比一般教科書的要...

C 記憶體管理詳解

踏入c 中的雷區 c 記憶體管理詳解 這篇文章回答了我之前的乙個問題,就是分配記憶體用malloc好,還是用new好,今天跑程式的時候,發現malloc老是失敗,氣得不行,最後看到了這篇文章,原來如此,以後堅決用new了。1 有了malloc free為什麼還要new delete?malloc與f...

C 記憶體管理詳解

1.對應的new和delete要採用相同的形式 下面的語句有什麼錯?string stringarray new string 100 delete stringarray 一切好象都井然有序 乙個new對應著乙個delete 然而卻隱藏著很大的錯誤 程式的運 況將是不可猜測的。至少,stringa...