对于C语言free()函数的一些反思

上周在解决一道课后习题的时候,偶然间发现了一个自己从未注意过的问题,问题描述如下:
在遍历一个循环链表时,我发现在我调用free()函数删除了一个节点之后,仍然能用printf打印出原先的数据,起初我以为是巧合,并未加以注意。今天我又尝试free其他节点,之后仍然能够通过printf打印出原先的值,这个问题立刻引起了我的注意。下面将出现问题的代码附在下方,供各位查看:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int status;
typedef int elemtype;
typedef struct node{
    elemtype data;
    struct node * next;
}node;
typedef struct node * linkqueue;

int main(void){
    linkqueue rear,pmove,head,qmove;
    int i=0;
    pmove=rear=(linkqueue)malloc(sizeof(node));
    if(!pmove||!rear)
       return ERROR;
    head=pmove;

    /*建立循环链表,并让0~9入队*/ 
    for(i=0;i<10;i++){
        qmove=(linkqueue)malloc(sizeof(node));
        qmove->data=i;
        rear->next=qmove;
        rear=qmove;
    }
    rear->next=head;
    pmove=head->next;

    printf("将0~9入队后\n");
    while(pmove!=head){
        printf("%d ",pmove->data);
        pmove=pmove->next;
    }
    printf("\n");

    /*出队算法*/ 
    pmove=head->next;
    printf("出队元素为:%d\n",pmove->data);
    linkqueue smove=pmove->next;
    free(pmove);
    ***printf("%d ",pmove->data);/*注意这行代码,这是问题之所在*/***
    pmove=smove;

    printf("出队后,遍历队列\n"); 
    while(pmove!=head){
        printf("%d ",pmove->data);
        pmove=pmove->next;
    }
    printf("\n");
}

从理论上看,free之后不应该打印出原数值,但事实是,我加粗的那行代码成功地打印出了原数值,在我google之后,得到了这样的解答:
“你在free(p)之后,最好加上p = NULL;

要不然容易导致野指针。你在free(p)之后,你只是使用
if(p != NULL)
你想的是用来进行防止误用操作对吧。。

你进入了一个误区,误认为free(p)之后,p就指向了NULL,而其实不然。

free(p)的言外之意就是告诉编译器:大家注意啦哈,这块内存我现在不用了,你们谁想用就拿去用哈。而p在这里你可以完全理解成就是这块内存的地址,也就是告诉编译器,这块内存现在不被占用了,而里面的内容此时就是我们所说的“垃圾”,因为作为主人的我已经丢弃它了,里面的内容就是不可控的。

注意p是个地址,你没有强行置为空,那还是原来的那个值。只是里面的内容不受控啦,有可能不会变,有可能会被改写,而结果是未知的。”

之前在知乎上总是看到大牛们大书特书C语言内存管理机制的缺陷,野指针的种种危害。却从未想过究竟什么是“野指针”,今天遇到的这个问题就是野指针带来的,看来自己对C指针的认识还不够深刻,还需要更深层次的学习,特地写下此文,加以反思。

看来水平离熟练使用C还差很远,静下心继续反思吧。

2016-04-27 晨
于教学实验综合楼

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C语言标准函数库是一组预定义的函数,提供了一系列常用的功能和操作,方便程序员编写和管理代码。C语言标准函数库分为几个不同的部分,比如输入输出函数、字符串函数、数学函数等。 要下载C语言标准函数库,首先需要确定所使用的开发环境。不同的开发环境可能有不同的方式下载标准函数库。通常情况下,C语言标准函数库已经被编译为开发环境所支持的库文件,并且自带于该环境中。 例如,对于常用的GNU C编译器(gcc),标准函数库是通过操作系统的包管理器进行安装的。在Linux操作系统上,通过运行适用于所使用的发行版的包管理器,可以轻松地安装C语言标准函数库。在Windows操作系统上,可以从MinGW等网站下载相应的GCC编译器,安装后即可使用标准函数库。 在其他开发环境中,可能需要手动下载标准函数库。可以通过搜索引擎查找相应的网站,从中找到可用的标准函数库版本并进行下载。下载完成后,根据开发环境的要求将库文件导入到项目中,并在代码中正确地引用函数库。 无论是自带于开发环境还是手动下载导入的方式,一旦成功下载C语言标准函数库,就可以在代码中使用其中的函数了。通过包含相应的头文件,并且调用所需的函数,即可实现所需的功能。 总结来说,下载C语言标准函数库的方法主要取决于所使用的开发环境。可以通过操作系统的包管理器进行安装,或者从相应的网站手动下载并导入到项目中。下载完成后,可以在代码中使用标准函数库提供的功能。 ### 回答2: C语言标准函数库是C语言编程中常用的一个库,包含了很多用来进行常见操作的函数。下载C语言标准函数库需要以下步骤: 首先,需要确定所使用的操作系统。因为不同的操作系统有不同的C语言编程环境和函数库支持。比如,在Windows系统下一般使用Visual Studio等集成开发环境,而在Linux系统下一般使用GCC编译器。 接下来,在相应的操作系统中安装C语言开发环境。对于Windows系统,可以下载并安装Visual Studio,或者MinGW等C编译器。对于Linux系统,可以使用apt-get、yum等包管理工具安装GCC编译器。 下载C标准函数库并将其添加到编译环境中。在Windows系统下,安装好Visual Studio等开发环境后,系统会自动默认包含C标准函数库,并在编译时链接。在Linux系统下,需要在编译时手动添加"-lm"参数,以链接C标准函数库。 需要注意的是,C标准函数库在编译时是自动链接的,不需要手动下载和安装。只需要确保所使用的C编译器支持C标准库,并将其链接到编译环境中即可。 综上所述,下载C语言标准函数库是通过安装相应的C开发环境来实现的。在已安装好的环境中,C标准函数库会自动包含并链接到编译环境中,无需额外下载和安装。 ### 回答3: C语言标准函数库是C语言提供的一套预定义函数集合,包含了各种常用函数,如字符串处理、数学运算、内存管理等。为了使用这些标准函数,需要将相应的函数库文件链接到我们的程序中。 在Windows环境下,我们可以通过下载安装MinGW或者Cygwin来获取C语言标准函数库。MinGW是一个实现了GCC编译器的开发环境,它包含了大多数C语言标准函数库,可以从MinGW官方网站下载并安装。Cygwin也是一个提供类Unix环境的兼容层,通过安装Cygwin,可以使用其中提供的标准函数库。 对于其他操作系统如Linux、Mac OS等,C语言标准函数库一般已经默认安装在系统中,我们可以直接在程序中调用这些函数,无需下载。 除了C语言标准函数库,还有一些第三方函数库可供下载使用,如Boost、OpenGL等。这些函数库提供了更多的功能和扩展性,可以满足特定的需求。下载和使用第三方函数库的方法一般是先从官方网站下载函数库的源代码,然后根据相应的安装说明进行编译和安装。 总之,C语言标准函数库是C语言开发中必不可少的一部分,通过下载和使用函数库,我们可以快速、方便地实现各种功能,提高开发效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值