函數內部使用malloc的幾種方法


需求

最近碰到一個需要在函數內部進行動態內存分配的需求,比如:

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);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM