天天看點

C語言:動态記憶體管理方式(malloc,calloc,realloc,free)為什麼要進行動态記憶體管理?進行動态記憶體管理的幾個函數

為什麼要進行動态記憶體管理?

普通的記憶體開辟方式有下面兩種:

int val = 1;//在棧空間上開辟4個位元組的空間
	char array[10] = {0};//在棧空間上開辟10個位元組的空間
           

但是,上面開辟空間的方式有缺陷:

  1. 開辟出來的空間大小是固定的;
  2. 數組在聲明時,必須指定數組的長度,它所需要的記憶體在編譯時配置設定;

是以,如果我想要靈活的申請空間,上面的方法顯然不能滿足,這是就需要利用動态記憶體開辟的方式來申請空間了。

進行動态記憶體管理的幾個函數

開辟空間的函數

1.malloc()函數

函數原型:

void* malloc ( size_t size );
           

malloc函數的作用就是在堆上申請一塊連續可用的空間,并傳回指向這片空間位址的指針。

在使用malloc函數時需要注意的地方:

  • 如果開辟成功,則傳回一個指向開辟好空間的指針。
  • 如果開辟失敗,則傳回一個NULL指針,是以malloc的傳回值一定要做檢查。
  • 傳回值的類型是 void* ,是以malloc函數并不知道開辟空間的類型,具體在使用的時候使用者自己來決定。
  • 如果參數 size 為0,malloc的行為是标準是未定義的,取決于編譯器。

2.calloc()函數

函數原型:

void* calloc ( size_t num, size_t size );
           
  • num:要配置設定的元素個數;
  • size:每個元素的大小;

calloc函數的功能與malloc函數的功能相同,都是用來在堆上申請空間的。不同的地方是:

calloc函數申請出來的空間會初始化為0 ;

除此之外,和malloc一樣。

3.realloc()函數

函數原型:

void* realloc ( void * ptr, size_t size );
           
  • ptr是要調整的記憶體的位址;
  • size是調整之後記憶體的大小;
  • 傳回值為調整之後的記憶體的起始空間位置;

realloc函數的也是用來在堆上申請空間的,但是realloc函數使動态記憶體管理更加的靈活。

realloc函數可以在已經申請好的記憶體空間上在追加記憶體空間。

在realloc函數申請記憶體空間時有兩種情況:

  1. 原有空間後有足夠大的空間;

    此時直接在原空間的後邊追加空間,傳回原有空間的首位址;

  2. 原有空間後的空間不夠所要追加的空間大小;

    在對空間上重新找一塊大小合适的連續空間,将原空間的内容拷貝一份,儲存到這塊大小合适的連續空間中,傳回這塊大小合适的空間的首位址;

    C語言:動态記憶體管理方式(malloc,calloc,realloc,free)為什麼要進行動态記憶體管理?進行動态記憶體管理的幾個函數

上面三個申請空間的函數有個必須要注意的地方:

  • 使用時,傳回值要強轉;
  • 使用這三個函數時,要包含stdlib,h頭檔案;

釋放記憶體空間的函數

4.free()函數

函數原型:

void* free ( void* ptr ) ;
           

free函數的作用是:釋放由malloc函數,calloc函數,realloc函數動态開辟的記憶體空間;

需要注意:

動态申請的記憶體空間,必須釋放,如果不釋放,會産生記憶體洩漏;

常見的動态記憶體錯誤

  • 對空指針的解引用;
void test()
{
 	int *p = (int *)malloc(INT_MAX/4);
 	*p = 20;//如果p的值是NULL,就會有問題
 	free(p);
}
           
  • 對動态開辟空間的越界通路;
void test()
{
 	int i = 0;
	int *p = (int *)malloc(10*sizeof(int));
 	if(NULL == p)
 	{
 		exit(EXIT_FAILURE);
	 }
 	for(i=0; i<=10; i++)
 	{
 		*(p+i) = i;//當i是10的時候越界通路
	 }
 	free(p);
}
           
  • 對非動态開辟記憶體使用free釋放;
void test()
{
	int a = 10;
 	int *p = &a;
	free(p);//ok?
}
           
  • 使用free函數釋放動态開辟記憶體的一部分;
void test()
{
	int * p = (int*) malloc (100);
	p++;
	free(p);//p不再指向動态記憶體的起始位置
}
           
  • 對同一塊動态記憶體多次釋放;
void test()
{
	int *p = (int*) malloc(100);
	free(p);
	free(p);//重複釋放
}
           
  • 動态開辟記憶體忘記釋放(記憶體洩漏);
void test()
{
	int* p = (int*) malloc(100);
	if(NULL != p)
	{
		*p = 20;
	}
}
int main ()
{
	test():
	
	return 0;
}
           

keep Running