C语言之free函数以及野指针介绍

所属分类: 软件编程 / C 语言 阅读数: 109
收藏 0 赞 0 分享

【FROM MSDN && 百科】
原型:void free(void *ptr);
#include<stdlib.h>或#include <malloc.h>
Deallocate space in memory
释放ptr指向的存储空间。被释放的空间通常被送入可用存储区池,以后可在调用malloc、realloc以及realloc函数来再分配。
注意:连续两次使用free函数,肯定会发生错误。malloc的次数要和free的次数相等。
A block of memory previously allocated using a call to malloc, calloc or realloc is deallocated, making it available again for further allocations.
If ptr does not point to a block of memory allocated with the above functions, the behavior is undefined.
If ptr is a null pointer, the function does nothing
Notice that this function does not change the value of ptr itself, hence it still points to the same (now invalid) location
DEMO:

复制代码 代码如下:

//#define  FIRST_DEMO
#define  SECOND_DEMO
#ifdef FIRST_DEMO
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{
 int *buffer1,*buffer2,*buffer3;
 buffer1=(int *)malloc(100*sizeof(int));
 buffer2=(int *)calloc(100,sizeof(int));
 buffer3=(int *)realloc(buffer2,500*sizeof(int));
 free(buffer1);
 free(buffer3);
 getch();
 return 0;
}
#elif defined SECOND_DEMO
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main(void)
{
 char *str;
 /*allocate memory for string*/
 str=(char *)malloc(10);
 if (str==NULL)
 {
  perror("malloc");
  abort();
 }
 else
 {
  /*copy "hello" to string*/
  strcpy(str,"hello");
  /*display string*/
  printf("String is %s\n",str);
  /*free memory*/
  free(str);
 }
 getch();
 return 0;
}
#endif

DEMO:perror
perror( ) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno 的值来决定要输出的字符串。
复制代码 代码如下:

#include <stdio.h>
#include <stdlib.h>   //perror包含在此文件中
#include <conio.h>
int main(void)
{
    FILE *fp;
 fp=fopen("abc","r+");
 if (NULL == fp)
 {
  perror("abc");
 }
 getch();
 return 0;
}

output:
abc: No such file or directory
DEMO:
复制代码 代码如下:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
 char *ptr;
 ptr=(char *)malloc(100);
 strcpy(ptr,"Hello");
 free(ptr);    //<span style="font-family: arial, 宋体, sans-serif; font-size: 13.63636302947998px; line-height: 24px; text-indent: 30px;">&nbsp;ptr 所指的内存被释放,但是ptr所指的地址仍然不变,原来的内存变为“垃圾”内存(不可用内存)</span>
#if 1
 if (ptr!=NULL)    /*<span style="font-family: arial, 宋体, sans-serif; font-size: 13.63636302947998px; line-height: 24px; text-indent: 30px;">&nbsp;没有起到防错作用</span>*/
 {
  strcpy(ptr," world");
  printf("%s\n",ptr);
 }
#endif
 getch();
 return 0;
}

free(str)后指针仍然指向原来的堆地址,即你仍然可以继续使用,但很危险,因为操作系统已经认为这块内存可以使用,他会毫不考虑的将他分配给其他程序,于是你下次使用的时候可能就已经被别的程序改掉了,这种情况就叫“野指针”,所以最好free()了以后再置空
str = NULL;
即本程序已经放弃再使用他。
何谓“野指针”,在这里补充一下。
野指针是指程序员或操作者不能控制的指针。野指针不是NULL指针,而是指向“垃圾”的指针。

造成“野指针”的原因主要有
1.指针变量没有初始化,
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。在初始化的时候要么指向合法的指针,要么指向NULL。

2.指针变量被free或delete之后,没有设置为NULL。它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。上文DEMO则是这种情况。

3.指针操作超越了变量的作用范围。注意其生命周期。

【下面是摘自论坛里面的形象比喻,加深理解。】
CRT的内存管理模块是一个管家。  
你的程序(简称“你”)是一个客人。  
管家有很对水桶,可以用来装水的。  
malloc的意思就是“管家,我要XX个水桶”。  
管家首先看一下有没有足够的水桶给你,如果没有,那么告诉你不行。如果够,那么登记这些水桶已经被使用了,然后告诉你“拿去用吧”。  
free的意思就是说:“管家我用完了,还你!”。  
至于你是不是先把水倒干净才给管家,那么是自己的事情了。--是不是清零。
  
管家也不会将你归还的水桶倒倒干清(他有那么多水桶,每个归还都倒干净岂不累死了)。反正其他用的时候自己会处理的啦。  
free之后将指针清零只是提醒自己,这些水桶已经不是我的了,不要再完里面放水了,^_^  
如果free了之后还用那个指针的话,就有可能管家已经将这些水桶给了其他人装饮料的了,你却往里面撒了泡尿。好的管家可能会对你的行为表示强烈的不满, 杀了你(非法操作)--这是最好的结果,你知道自己错了(有错就改嘛)。一些不好的管家可能忙不过来,有时候抓到你作坏事就惩罚你,有时候却不知道去那里 了--这是你的恶梦,不知道什么时候、怎么回事情自己就死了。不管怎么样,这种情况下很有可能有人要喝尿--不知道是你的老板还是你的客户了.^_^。  
所以啊,好市民当然是还了给管家的东西就不要再占着啦,.^_^。

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多