前言
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
段错误 (核心已转储)
此时的“段错误”是如此的亲切,爱你呦!