C語言動態內存管理


在C語言中,編寫程序的時候不能確定內存的大小,希望程序在運行的過程中根據數據量的大小動態的分配內存。動態內存管理,就是指在程序運行過程中動態的申請和釋放內存空間。

C語言允許程序動態管理內存,需要時隨時開闢,不需要時隨時釋放。內存的動態管理是通過調用庫函數來實現的,主要有malloc和free函數。

一、相關的庫函數

1、malloc 函數

函數的原型:

void *malloc(unsigned int size)

malloc的作用是向系統申請一塊大小爲size的連續內存空間,如果申請失敗,函數返回0,如果申請成功,返回成功分配內存塊的起始地址。

例如:

malloc(100)// 申請 100 個字節的臨時分配域,返回值爲其第一個字節的地址

malloc的返回值的地址的基類型爲void,即不指向任何類型的數據,只提供一個地址,程序中需要定義一個指針來指向動態分配的內存地址。

例如:

int *pi=malloc(sizeof(int));

2、free 函數

函數的原型:

void free(void *p);

free的作用是釋放指針p指向的動態內存空間,p是調用malloc函數時返回的地址,free函數無返回值。

例如:

free(pi);     // 釋放指針變量pi指向的已分配的動態空間

示例(book107.c)

/*
 * 程序名:book107.c,此程序用於演示C程序動態內存管理。
 * 作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct st_girl  // 超女結構體
{
  char name[50];     // 姓名
  int  age;          // 年齡
};

int main(int argc,char *argv[])
{
  int    *pi=malloc(sizeof(int));    // 分配int類型大小的內存
  long   *pl=malloc(sizeof(long));   // 分配long類型大小的內存
  double *pd=malloc(sizeof(double)); // 分配double類型大小的內存
  char   *pc=malloc(101);            // 分配101字節的內存,可存放100個字符的字符串
  struct st_girl *pst=malloc(sizeof(struct st_girl)); // 分配struct st_girl結構體大小的內存

  // 以下代碼是像普通指針和變量一樣使用動態分配的內存
  *pi=10;     printf("*pi=%d\n",*pi);
  *pl=20;     printf("*pl=%d\n",*pl);
  *pd=10.5;   printf("*pd=%.1f\n",*pd);
  strcpy(pc,"西施"); printf("*pc=%s\n",pc);
  strcpy(pst->name,"楊玉環"); pst->age=21;
  printf("name=%s,age=%d\n",pst->name,pst->age);
  
  // 釋放動態分配的內存
  free(pi); free(pl); free(pd); free(pc); free(pst);
}

運行效果

在這裏插入圖片描述

二、內存被耗盡

使用動態分配內存技術的時候,分配出來的內存必須及時釋放,否則會引起系統內存耗盡,這話說起來簡單,好像很容易做到,但是在實際開發中,程序員往往是漏洞百出。

內存問題是C程序員的主要問題之一,是初學者的惡夢。

三、野指針

野指針就是無效的指針,與空指針不同,野指針無法通過簡單地判斷是否爲 NULL避免,而只能通過養成良好的編程習慣來盡力減少。

1、指針變量未初始化

指針變量剛被創建時不一定會自動初始化成爲空指針(與編譯器有關),它的缺省值是可能隨機的,它會隨便亂指。所以,指針變量在創建的同時應當被初始化,要麼將指針的值設置爲0,要麼讓它指向合法的內存。

int *pi=0;

int i;
int *pi=&i;

2、指針釋放後之後未置空

指針在free時會把指針所指的內存給釋放掉,但指針不一定會賦值0(也與編譯器有關),如果對釋放後的指針進行操作,相當於非法操作內存。釋放內存後應立即將指針置爲0。

free(pi);
pi=0;

四、應用經驗

1、數組申明的改進

在C語言的早期標準中,定義數組必須用常量指明大小,不能用變量。

char str[101];        // 可以這樣
int len=101;
char str[len];         // 不可以這樣

程序在運行的時候,如果要定義一個字符串存放100個字符,那怎麼辦,只能通過動態分配內存技術。

char *str=malloc(101);

現在,定義數組可以用變量指明大小,就不必爲數組動態分配內存了。

還有,C++的string是一個變長的字符串,非常好用,程序員根本不必關心內存的問題。

2、鏈表

鏈表是C語言的一個經典的數據結構,相當於一個動態的結構體數組,非常巧妙,功能強大,但操作也麻煩,在這裏我就不介紹了。

在C++中,容器全完代替了鏈表的功能,極其好用,程序員也不必關心內存的問題。

3、我的建議

在中國,沒有純C程序員,如果他不會C++,不是他對C有多麼執着,可能是不會C++。

至少十年了,我不再使用動態內存分配技術,也想不到有什麼場景非得用動態內存分配技術。

哦,嵌入式開發可能是個例外,可能還有其它只能用C不能用C++的場景。

動態內存分配並不是什麼高大上的技術,我是一個實用的程序員,絕不給自己挖坑,這與水平高低無關。

五、課後作業

編寫示例程序,把本章節介紹的知識點全部演示一遍,用程序演示可以加深您的理解和映象。

六、版權聲明

C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。
來源:C語言技術網(www.freecplus.net)
作者:碼農有道

如果文章有錯別字,或者內容有錯誤,或其他的建議和意見,請您留言指正,非常感謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章