zoukankan      html  css  js  c++  java
  • 函数内部使用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
    ",p_data2);
    
        //3.【错误】func3结束后p空间被释放,相对于func2,因为malloc分配的空间没有free是不会释放掉的
        //   所以func2返回指向的是malloc空间,而func3返回后访问的是野指针
        // char *p_data3;
        // p_data3 = func3();
        // printf("%s
    ",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
    ",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
    ", 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);
    
  • 相关阅读:
    tornado用户验证
    tornado cookie安全性
    XSS攻击
    《R语言入门》语言及环境简单介绍
    angular学习(十五)——Provider
    Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
    Windows之Xmanager连接linux打开Oracle视图操作
    CreateEvent和SetEvent及WaitForSingleObject的使用方法
    利用Sharepoint 创建轻量型应用之基本功能配置!
    android开发源代码分析--多个activity调用多个jni库的方法
  • 原文地址:https://www.cnblogs.com/fancyop/p/12680941.html
Copyright © 2011-2022 走看看