原文链接:http://blog.csdn.net/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来避免。对野指针进行操作很容易造成程序错误。
有时也把野指针和悬空指针通称为悬空指针。