malloc 与 free 相关的几个例子

实例1:

分析下面代码是否有错误?指出错误后果,并修改成正确的代码。

void GetMemory(char *p)
{
  p = (char *)malloc(100);
}
 
void Test(void)
{
  char *str = NULL;
  
  GetMemory(str);
  
  strcpy(str, "hello world");
  
  printf(str);
}

分析:在 Test 函数中调用 GetMemory(str); 后,实参 str 并未发生改变,依然是 NULL。在C语言中,形参值的改变并不能影响实参值。因为实参和形参是属于两个不同的存储空间,实参 —> 形参 是值传递,即它是一次内存拷贝的过程。

结果:当程序运行到 strcpy(str, "hello world"); 时,会产生错误,程序崩溃。

修改:可以使用二级指针的形式,正确代码如下:

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
    char *str=NULL;
    GetMemory(&str, 100);
    strcpy(str,"hello world");
    printf(str);
    free(str);
}

/**分析如下:
1)指针变量 str 本身占用一个4字节的存储单元,这个存储单元自己也是有一个地址值的,用 &str 来表示
2)将 &str 作为实参传递给形参 p,那么二级指针 p 就指向了指针变量 str。二级指针就是指向指针的指针
3)*p 运算就是指针 p 指向的指针变量 str 的值,然后将malloc动态申请的内存的首地址赋值给*p,就是赋
值给指针变量str,也就是说str存放的就是这个动态内存空间的首地址,亦即指针str指向了这块动态分配的内
存空间。
*/

<Tips> 在函数参数中使用二级指针的方式,可以把在一个函数内使用 malloc 动态分配的内存空间的首地址带出函数来,然后在其他地方就可以使用这片动态申请的内存空间了。

实例2:

分析下面代码是否有错误?指出错误后果,并修改成正确的代码。 

char* GetMemory(void)
{
  char p[] = "hello world";        //用字符串常量来初始化数组的内存空间
  //printf("address p: %#p\n", p); //address p: 0X000000000061FDA4
  return p;                        //编译器发出警告: warning: function returns address of 
                                   //local variable
}

void Test(void)
{
  char *str = NULL;
  str = GetMemory();
  //printf("address str: %#p\n", str); //address str: 0000000000000000
  printf(str);
}

分析:在 GetMemory() 函数中,试图返回数组变量 p 的首地址,但是数组p是函数 GetMemory 内的局部变量,而局部变量是存放在进程空间的栈区中的,当 GetMemory 函数执行结束时,为数组p分配的内存空间也会随之被自动释放掉。因此,在Test函数中,并不能输出正确的结果。

结果:输出的结果为空或者是乱码,这取决于编译器的编译处理。

修改:修改方式有两种,具体代码如下:

//方式1-将数组改成指针,然后返回指针变量(最简单)
char* GetMemory(void)
{
  char *p = "hello world";
  return p;
}

//方式2-使用二级指针的方式
char* GetMemory(char **p)
{
  *p = "hello world";
  return *p;
}

void Test(void)
{
  char *str = NULL;
  str = GetMemory(&str);
  printf(str);
}

<Tips> 在函数内,不要用 return 语句返回指向“栈内存”的指针,因为栈内存在函数结束运行时将会被系统自动释放掉。

实例3:

分析下面代码是否有错误?指出错误后果,并修改成正确的代码。

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(num);
}

void Test(void)
{
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello world");
    printf(str);
}

分析:在 GetMemory 函数中,使用 malloc 动态分配了内存,但是没有释放。在 Test 函数中可以输出 "hello world",但是会存在内存泄漏的风险。

修改:在 Test 函数中添加一条语句:free(str);

<Tips> 使用 malloc 或者 calloc 动态分配内存空间时,使用完后,一定要记得使用 free 将动态申请的内存释放掉。

实例4:

分析下面代码是否有错误?指出错误后果,并修改成正确的代码。

void Test(void)
{
    char *str = (char *)malloc(100);
    strcpy(str, "hello");
    free(str);
    if(str != NULL)
    {
        strcpy(str, "world");
        printf(str);
    }
}

分析:篡改动态内存区的内容,后果难以预料,非常危险。因为 free(str) 后,str指针就变成野指针了。if(str != NULL) 这个条件表达式是不起作用的,因此 if 语句块一定会被执行。

修改:在 free(str); 语句下面添加一条语句:str = NULL;

<Tips> free 掉一个指针后,最好马上将其赋值为NULL,不然容易导致野指针的出现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值