free(ptr) 之后

前言

free(ptr)之后,有时会是血雨腥风!


请看代码,如下:
#include <stdio.h>
#include <stdlib.h>

#define OK 0
#define ERROR 1

int main(void)
{
	//动态分配内存
    int *num = (int *)malloc(sizeof(int));
    if (NULL == num) {
        return ERROR;
    }
    
	//在分配的内存中写入数据
    *num = 666;
	
	//释放分配的内存
    free(num);
    
    return OK;
}

以上代码最后执行return OK,但其实并不OK,如下:

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

#define OK 0
#define ERROR 1

int main(void)
{
    int *num = (int *)malloc(sizeof(int));
    if (NULL == num) {
        return ERROR;
    }

    *num = 666;
    printf("value_1: %d\n", *num);
    printf("addr_1: %#x\n", num);

    free(num);
    printf("value_2: %d\n", *num);
    printf("addr_2: %#x\n", num);

    return OK;
}

执行结果:

value_1: 666
addr_1: 0x7ff260
value_2: 0
addr_2: 0x7ff260

可以看到,free(num);后,尽管指针指向的内存里面的数据已经被系统重置为0,但,
释放后,指针num还在指向释放之前的内存!
释放后,指针num还在指向释放之前的内存!
释放后,指针num还在指向释放之前的内存!

所以,这其实是“假释”,这就像把钓到的鱼放回水里,却没有拆掉它嘴里的鱼钩,,,

请再看:

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

#define OK 0
#define ERROR 1

int main(void)
{
    int *num = (int *)malloc(sizeof(int));
    if (NULL == num) {
        return ERROR;
    }

    *num = 666;
    printf("value_1: %d\n", *num);
    printf("addr_1: %#x\n", num);

    free(num);
    printf("value_2: %d\n", *num);
    printf("addr_2: %#x\n", num);
	
	//以下是一个禁止的操作,仅供学习使用(高危警告!):
    *num = 888;
    printf("value_3: %d\n", *num);
    printf("addr_3: %#x\n", num);

    return OK;
}

运行结果:

value_1: 666
addr_1: 0x2033260
value_2: 0
addr_2: 0x2033260
value_3: 888
addr_3: 0x2033260

这里,free之后,操作系统会将num指针指向的堆内存A收回,重置后再分配给其他需要堆内存的程序使用。
假如,此时另有一程序X申请了一块堆内存B,好巧不巧的,B包含了A,程序X在堆内存B中写入数据777后读取,然后悲催的发现,读取的结果里面时不时出现888,看程序X的源码也没有发现888,然后就可能发生“轻则砸键盘、砸电脑,重则杀个程序猿祭天”之类的惨剧。

总结

everybody 一起来,三遍!

free(ptr);之后,ptr = NULL;
free(ptr);之后,ptr = NULL;
free(ptr);之后,ptr = NULL;

最后,请看:

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

#define OK 0
#define ERROR 1

int main(void)
{
    int *num = (int *)malloc(sizeof(int));
    if (NULL == num) {
        return ERROR;
    }

    *num = 666;
    printf("value_1: %d\n", *num);
    printf("addr_1: %#x\n", num);

    free(num);
    //以下置空语句就很nice,很安全!
    num = NULL;
    printf("value_2: %d\n", *num);
    printf("addr_2: %#x\n", num);

    *num = 888;
    printf("value_3: %d\n", *num);
    printf("addr_3: %#x\n", num);

    return OK;
}

free后置空,运行结果:

value_1: 666
addr_1: 0x462260
段错误 (核心已转储)

此时的“段错误”是如此的亲切,爱你呦!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值