需求
最近碰到一個需要在函數內部進行動態內存分配的需求,比如:
void func1(char *p)
{
int n;
//... 給n賦值
p = (char *)malloc(sizeof(char)*n);
//... 向*p寫數據
}
int main(int argc, char *argv[])
{
char *p_data;
func1(p_data);
//...
return 0;
}
上代碼用來簡單描述任務需求,目是說明一定需要在函數內部調用malloc分配內存空間,但像上面那樣直接分配就會導致函數func1結束后,指針p被釋放掉(malloc分配的空間並沒有被釋放)所以,就找不到之前malloc分配的堆空間。
示例1:一維
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func1(char *p)
{
p = (char *)malloc(sizeof(char)*10);
}
char* func2(char *p)
{
p = (char *)malloc(sizeof(char)*10);
return p;
}
char* func3(void) //warning: function returns address of local variable
{
char p[] = "three";
return p;
}
void func4(char **p)
{
*p = (char *)malloc(sizeof(char)*10);
}
int main(int argc, char *argv[])
{
//1.【錯誤】訪問空指針導致越界,因為func1結束后p被釋放,malloc分配的空間沒有釋放
// char *p_data1;
// func1(p_data1);
// strcpy(p_data1, "one"); //Segmentation fault (core dumped)
// printf(p_data1);
//2.【正確】通過return返回指針,用來指向malloc分配的內存空間
char *p_data2;
p_data2 = func2(p_data2);
strcpy(p_data2, "two");
printf("%s\n",p_data2);
//3.【錯誤】func3結束后p空間被釋放,相對於func2,因為malloc分配的空間沒有free是不會釋放掉的
// 所以func2返回指向的是malloc空間,而func3返回后訪問的是野指針
// char *p_data3;
// p_data3 = func3();
// printf("%s\n",p_data3); //Segmentation fault (core dumped)
//4.【正確】func4傳入的是 &p_data4 它指的是傳入的是指針p_data4所位於的內存地址
// 而相對於func2傳入的是 p_data2 它指的是傳入的是指針p_data2所指向的內存空間
// 這樣說可能還有點蒙,舉個例子某高速路上【杭州路段】有塊【標識牌】,上面寫着
// 【距離上海還有XXXkm】,這個路牌它所在地址是【杭州】,但是它指向的是【上海】
// 相對於p_data4就類於【杭州】,p_data2類於【上海】
char *p_data4;
func4(&p_data4);
strcpy(p_data4, "four");
printf("%s\n",p_data4);
return 0;
}
相對於func4而言,func2就顯得有些臃腫,不過效果都能同樣實現,輸出結果:
two
four
示例2:二維
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func5(char ***p, int *len)
{
char aa[] = "wersdfsdfsd";
char bb[] = "jgj645675476345634563456345";
char cc[] = "123";
(*p) = (char **)malloc(3*sizeof(char));
(*p)[0] = (char *)malloc(strlen(aa)*sizeof(char));
(*p)[1] = (char *)malloc(strlen(bb)*sizeof(char));
(*p)[2] = (char *)malloc(strlen(cc)*sizeof(char));
strcpy((*p)[0], aa);
strcpy((*p)[1], bb);
strcpy((*p)[2], cc);
*len = 3;
}
int main()
{
int i, length;
char **str;
func5(&str, &length);
for (i = 0; i < length; i++)
{
printf("-%02d- %s\n", i, str[i]);
}
return 0;
}
輸出結果:
-00- wersdfsdfsd
-01- jgj645675476345634563456345
-02- 123
拓展:
根據申請方式不同,棧(stack)由系統自動分配,堆(heap)需要程序員自己申請。
char str1[20]; //棧
char *str2;
str2 = (char *)malloc(sizeof(char)*10); //堆
malloc分配的空間在進程結束之前不會主動釋放,需要手動釋放執行free
char *str;
str = (char *)malloc(sizeof(char)*10);
free(str);