《 C Primer Plus (第六版)中文版 》 书中的一处勘误

来源:互联网 发布:黄金买卖交易软件 编辑:程序博客网 时间:2024/06/10 16:08


出错的地方:
第17章高级数据表示
17.2.1 使用链表
17.2 films2.c程序
第574页
下面是程序清单,红色框内的代码是出错的地方。


这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述
作者的本意是想把current指向链表的开头结点,head指向下个结点,然后free当前结点,并判断是否是最后一个结点,不是的话就循环,保存下个结点的head的值再赋给curent ,head指向下一个结点,再free当前结点。。。依此类推,直到最后一个结点NULL, 循环结束。
表面看这个逻辑没任何问题。但是由于逻辑上的不严谨,这里程序产生了bug。
这段代码有两个很明显的错误,分析如下:
第一,先不理会这段代码循环了多少次。循环的最后一行free 了current指针 ,然后回过头来再判断current是否为NULL.注意,这个地方在使用野指针了。因为free之后,原先申请到的内存空间已经返回给系统了,所以current已经指向一个不合法的内存空间。此时对current的任何操作都是错误的。
第二,因为是先free current再判断current是否为NULL,所以free的次数会比malloc多一次。
执行上面程序,运行结果显示是段错误,我们来分析为什么会产生段错误。
假设一共有3个结点。循环第一次后,head指向第2个结点,第1个结点被free掉。
循环第二次后,head指向第3个结点,第2个结点被free掉。
循环第三次后,head指向第4个结点,是不存在的结点,为NULL,第3个结点被free掉。
循环第四次,current指向第4个结点NULL,head = current -> next 变成了这样子
head = NULL -> next。然而NULL是系统定义的0地址,我们知道计算机的低地址空间是不允许被访问的。这里试图操作内存低地址空间所以就产生了段错误。
虽然文章后面也讲了films2.c程序的一些不足。但是上面写到的错误明显是作者的不细心造成的。(也有可能是翻译错了,因为英文版的书我没有看过。)
下面修改之后的代码:
// 释放内存
current = head;
while(current != NULL)
{
head = current -> next;
free(current);
current = head;
}
最后说一句,很多程序的BUG都是来源于逻辑上的不严谨,还有就是没有养成好的编程习惯。

原创粉丝点击