free 引发的思考

本文探讨了`free`函数在释放内存时可能导致的问题,包括重复释放同一内存区域可能导致未定义行为。作者通过实例展示了即使没有立即出现问题,也应避免多次调用`free`。文章还提醒读者在释放内存后将指针设为NULL以防止悬空指针,并区分了悬空指针和野指针的概念。

原文链接:http://blog.youkuaiyun.com/lyh__521/article/details/49539011

先看两个例子:

(1)

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    char  *p;
    char  *q;
    p = (char*)malloc(20);   // 给p开辟空间
    q = p;                   // 赋值后,p与q 指向同一块内存

    free(p);                 // 释放 p 指向的内存
    printf("p=%p\n",p);      // 输出地址

    free(q);                 // 再次释放内存
    printf("q=%p\n",q);      // 输出地址

    return 0;
}

结果和预想的一样,因为对同一块内存释放了两次,所以出现了段错误
这里写图片描述

(2)
我们给中间插入一段代码:

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    char  *p;
    char  *q;
    p = (char*)malloc(20);   // 给p开辟空间

    char  *p1;               // ------- 
    p1 = (char*)malloc(20);
    strcpy(p1,"hello,world");
    printf("%s\n",p1);       // -------

    q = p;                   // 赋值后,p与q 指向同一块内存

    free(p);                 // 释放 p 指向的内存
    printf("p=%p\n",p);      // 输出地址

    free(p1);                // 释放p1

    free(q);                 // 再次释放内存
    printf("q=%p\n",q);      // 输出地址

    return 0;
}

这里写图片描述

。。。运行结果颠覆了我对free的认知,还是对同一块内存free了两次但是却没出现异常,只是在中间穿插了一些别的代码而已,难道free还有其他的特性?

free

然后我查看了free的文档,介绍是这样的:
这里写图片描述

  可以看到,标准里并没有明确指出 free 多次会产生什么后果,只是说对一段已经释放过的内存释放多次产生的行为是未定义的。就像上面的例子,可能有时会没问题,有时会段错误,也可能产生更严重的后果。
  所以,不要以为free多次运行正常就可以这样写,要记得避免重复free.

怎么避免重复free?

  上面的标准文档里明确说明:如果指针为NULL,则不会对其执行操作。所以,free 前可以判断一下,释放完一段内存后,要把指针置为NULL,这样也可以避免产生悬空指针。

就像下面这样:

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    char  *p;
    p = (char*)malloc(20);   // 给p开辟空间
    strcpy(p,"hello,world");
    printf("%s\n",p);

    if(p != NULL)
    {
        free(p);
        p = NULL;
    }

    free(p);                 // 即使再次free也不会有问题
                             // 可以free空指针
    return 0;
}

悬空指针

一个指针的指向对象已被删除,那么这个指针就成了悬空指针。

野指针

野指针是指未初始化的指针。野指针与空指针不同,无法通过简单的判断是否为NULL来避免。对野指针进行操作很容易造成程序错误。

有时也把野指针和悬空指针通称为悬空指针。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值