C語言動態(tài)內存分配圖文講解
思維導圖

1.為什么存在動態(tài)內存分配
我們現(xiàn)在學習了一些內存開辟的方式:
int main()
{
int i;//在內存棧區(qū)開辟4個字節(jié)空間
char arr[5];//在棧空間上開辟5個字節(jié)的連續(xù)空間
return 0;
}但是,這樣開辟的內存是靜態(tài)的,固定的:
1. 空間開辟大小是固定的。
2. 數(shù)組在申明的時候,必須指定數(shù)組的長度,它所需要的內存在編譯時分配。
如果想要在編譯過程中開辟空間,就需要用到動態(tài)內存。
2.動態(tài)內存函數(shù)的介紹
2.1 malloc
void* malloc (size_t size)
2.2 free
void free (void* ptr)
例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//申請40給字節(jié),用來存放10個整形
int* p = (int*)malloc(40);//malloc申請的空間不會初始化
if (p == NULL) //直接返回起始地址
{
perror("malloc");//如果空間開辟失敗要報錯并返回
return 1;
}
//使用空間
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d\n", *(p + i));
}
//釋放申請的內存
free(p);
p = NULL;
return 0;
}輸出:
輸出:
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
malloc不會自己初始化,所以打印隨機值。
例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//申請40給字節(jié),用來存放10個整形
int* p = (int*)malloc(40);//malloc申請的空間沒有初始化
if (p == NULL) //直接返回起始地址
{
perror("malloc");//如果空間開辟失敗要報錯并返回
return 1;
}
//使用空間
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i + 1;//初始化賦值
printf("%d ", *(p + i));
}
//釋放申請的內存
free(p);
p = NULL;
return 0;
}輸出:
輸出:1 2 3 4 5 6 7 8 9 10
2.3 calloc
void* calloc (size_t num, size_t size)
例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));//10是要初始化的個數(shù),sizeof(int)是每個的大小
if (NULL == p)
{
perror("calloc");//判斷內存是否申請成功
return 1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));//calloc申請空間后,會把空間初始化成0
} //再返回起始地址
//釋放
free(p);
p = NULL;
}輸出:
輸出:0 0 0 0 0 0 0 0 0 0
2.4 realloc
void* realloc (void* ptr, size_t size)
realloc函數(shù)可以追加更多動態(tài)內存。
例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(5 * sizeof(int));//開辟一段動態(tài)內存20個字節(jié)
if (NULL == p)
{
perror("malloc");//檢查是否創(chuàng)建成功
return 1;
}
//使用
int i = 0;
for (i = 0; i < 5; i++)
{
*(p + i) = i + 1;
}
//不夠用,增加5個整形的空間
int* ptr = (int*)realloc(p, 10 * sizeof(int));//這里是開辟到40個字節(jié)
//realloc函數(shù)開辟內存空間有兩種情況:
//1.原內存塊后面空間足夠,在原內存塊后面追加內存
//2.原內存塊后面空間不夠,另外找一片區(qū)域開辟內存,將原內存塊釋放
if (ptr != NULL)
{
p = ptr;//為什么不直接用p接收?
//如果內存追加失敗,直接用p接收的話,原本已經(jīng)開辟的動態(tài)內存空間就會被覆蓋
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
//釋放
free(p);
p = NULL;
return 0;
}輸出:
輸出:1 2 3 4 5 -842150451 -842150451 -842150451 -842150451 -842150451
3.常見的動態(tài)內存錯誤
例1:
開辟動態(tài)內存記得要判斷,最后釋放內存。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(100);
//內存開辟后沒有判斷是否開辟成功
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = 0;//危險代碼,我們無法知道是否存在非法訪問
}
//并且最后也沒有將開辟的內存還給操作系統(tǒng)
return 0;
}例2:
動態(tài)內存開辟了多少就用多少,小心越界訪問。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(100);//開辟了100字節(jié)空間
//判斷
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0; i < 100; i++)//造成越界訪問
{
*(p + i) = 0;//一個整形4個字節(jié)
}
//釋放
free(p);
p = NULL;
return 0;
}例3:
不要亂釋放其他內存空間。
int main()
{
int a = 10;
int* p = &a;
//你沒有權限亂釋放其他的內存空間
free(p);//不能對棧區(qū)的內存釋放
return 0;
}例4:
不要多次釋放內存空間。
#include <stdio.h>
#include <stdlib.h>
int main()
{
//開辟空間
int* p = (int*)malloc(100);
//判斷
if (p == NULL)
{
perror("malloc");
return 1;
}
//使用
int i = 0;
for (i = 0; i < 25; i++)
{
*p = i;
p++;//p指針不斷往后移動
}
//釋放的時候指針應該指向起始地址,否則程序又會出錯
free(p);
p = NULL;
return 0;
}例5:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//創(chuàng)建
int* p = (int*)malloc(100);
//判斷
if (p == NULL)
{
return 1;
}
//釋放
free(p);
free(p);//已經(jīng)釋放了,重復釋放會導致程序出錯
return 0;
}這就要說到最后置為空指針的好處了:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//創(chuàng)建
int* p = (int*)malloc(100);
//判斷
if (p == NULL)
{
return 1;
}
//釋放
free(p);
p = NULL;//置為空指針后程序就不會崩潰了
free(p);//p為空指針時,程序不會報錯
return 0;
}例5:
在實現(xiàn)函數(shù)時開辟了動態(tài)內存要記得及時釋放或者返回地址,
不然就再也找不到那段內存空間了,最后導致內存泄漏。
#include <stdio.h>
#include <stdlib.h>
void test()
{
int* p = (int*)malloc(100);
//忘記釋放
}//出了函數(shù)就找不到了,因為變量p被銷毀了
//造成內存泄漏
int main()
{
test();
return 0;
}
例6:
這道題也是類似的:
#include <stdio.h>
#include <stdlib.h>
void test()
{
int* p = (int*)malloc(100);
if (p == NULL)
{
return;
}
//使用
if (1)
return;//出問題//內存泄漏
//釋放
free(p);
p = NULL;
}
int main()
{
test();
return 0;
}要小心出現(xiàn)內存泄漏,記得釋放空間。
到此這篇關于C語言動態(tài)內存分配圖文講解的文章就介紹到這了,更多相關C語言動態(tài)內存分配內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

