在看 apue 第 21 章 与网络打印机通信一章时,发现一段关于链表操作的代码有问题,现在摘出来让大家 review 一下。先上代码:

printd.c

这是打印服务的源代码,在打印时,用户通过  print 命令提交待打印的文件,print 命令通过 tcp 与 printd 服务通讯,

将文件及打印相关的参数传递给后者;对于每个客户,printd 服务会创建一个 worker 结构节点,

放在一个由 workers 变量指定了头的双向链表中。所以这段代码本质上就是简单的双向链接操作:

 1 void add_worker (pthread_t tid, int sockfd)
2 {
3 struct worker_thread *wtp;
4 if ((wtp = malloc (sizeof (struct worker_thread))) == NULL) {
5 log_ret ("add_worker: can't malloc");
6 pthread_exit ((void *)1);
7 }
8
9 wtp->tid = tid;
10 wtp->sockfd = sockfd;
11
12 log_msg ("prepare to add worker");
13 pthread_mutex_lock (&workerlock);
14
15 wtp->prev = NULL;
16 wtp->next = workers;
17 if (workers == NULL)
18 workers = wtp;
19 else
20 workers->prev = wtp;
21
22 pthread_mutex_unlock (&workerlock);
23 }

重点就是 15-20 这 6 行啦(原文p633,代码499-504行),当第一次加入节点时, workers 为 NULL,所以走第一个条件分支,这没有问题;

但是再加入节点时, workers 不为 NULL,此时走 else 分支,将当前头的上一个节点设置为待插入的新节点  wtp,

到现在还好,可是等等,怎么就没下文了?!这个节点还没完全加入链表呢……

正确的做法应该是在结尾前再加一句:

    else
{
workers->prev = wtp;
workers = wtp;
}

这样才能算完嘛。道理就不多说了,不信自己画个链表看看。下面给出优化后的完整代码:

 1 void add_worker (pthread_t tid, int sockfd)
2 {
3 struct worker_thread *wtp;
4 if ((wtp = malloc (sizeof (struct worker_thread))) == NULL) {
5 log_ret ("add_worker: can't malloc");
6 pthread_exit ((void *)1);
7 }
8
9 wtp->tid = tid;
10 wtp->sockfd = sockfd;
11 pthread_mutex_lock (&workerlock);
12
13 wtp->prev = NULL;
14 wtp->next = workers;
15 if (workers != NULL)
16 workers->prev = wtp;
17
18 workers = wtp;
19
20 pthread_mutex_unlock (&workerlock);
21 }

好吧,我承认作为经典著作也会有这种低级错误。

今天的吹毛求疵就到这里,作为一个有职业素养的程序员,不在鸡蛋里挑出骨头来不罢休,嘿嘿……

[apue] 书中关于打印服务代码的一个错误的更多相关文章

  1. 关于Java中的继承和组合的一个错误使用的例子

    [TOC] 关于Java中的继承和组合的一个错误使用的例子 相信绝大多数人都比较熟悉Java中的「继承」和「组合」这两个东西,本篇文章就主要就这两个话题谈论一下.如果我某些地方写的不对,或者比较幼稚, ...

  2. 路由器安装ubuntu-16.04.1-server-amd64出现“无法安装busybox-initramfs”错误。向目标系统中安装busybox-initramfs软件包时出现一个错误。请检查/var/log/syslog或查看第四虚拟控制台以获得详细

    公司的路由器要ubuntu服务器进行路由网络功能的管理,在安装的时候出现下面的错误提示: 安装ubuntu-16.04.1-server-amd64出现“无法安装busybox-initramfs”错 ...

  3. APUE 书中 toll 函数

    今天看unix环境高级编程时,随着书上的源码打了一遍,编译时提示 toll函数未定义, 找了半天(恕我对上下文不了解).看了英文版和源代码文件才知道, 中文版打印错了: toll => atol ...

  4. C# sliverlight调用WCF服务出现的一个错误

    错误提示如下: 尝试向 URI“http://localhost:8396/Service1.svc”发出请求时出错.这可能是由于试图以跨域方式访问服务而又没有正确的跨域策略,或策略不适用于 SOAP ...

  5. [apue] 书中关于伪终端的一个纰漏

    在看 apue 第 19 章伪终端第 6 节使用 pty 程序时,发现“检查长时间运行程序的输出”这一部分内容的实际运行结果,与书上所说有出入. 于是展开一番研究,最终发现是书上讲的有问题,现在摘出来 ...

  6. unix编程书中的 ourhdr.h代码

    真心不知到里面写的具体什么意思,先记下吧. /*Our own header, to be included after all standard system headers*/ #ifndef _ ...

  7. IIS8中部署WCF服务出错:HTTP 错误 404.3 - Not Found

    解决方法,以管理员身份进入命令行模式,运行: "%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ ...

  8. 解决android调用IIS Express中的WCF服务时,出现错误400问题

    IIS Express仅支持localhost主机名地址访问. 找到IIS Express Config文件下的 applicationhost.confi   修改配置 再来调试android应用, ...

  9. 在commons-lang3包中StringUtils类的ordinalIndexOf中有一个错误

    * StringUtils.ordinalIndexOf(null, *, *) = -1 * StringUtils.ordinalIndexOf(*, null, *) = -1 * String ...

  10. 如何自己编译apue.3e中代码 & 学习写makefile

    本来是搜pthread的相关资料,看blog发现很多linux程序员都看的一本神书<APUE>,里面有系统的两章内容专门讲pthread(不过是用c语言做的代码示例,这个不碍事,还是归到原 ...

随机推荐

  1. LVM精简卷(Thinly-Provisioned Logical Volumes)

    可能LVM大家都比较熟悉,那么精简卷又是干什么的呢?相比于普通LVM有什么优势,又会带来哪些新的问题?带着这些我们来一探究竟: 工作原理 在创建Thin"瘦"卷时,预分配一个虚拟的 ...

  2. CSS实现导航栏

    1.知识点 列表 浮动 伪类 背景 文本格式化 盒子模型 2.效果 3.代码 <!DOCTYPE html> <html lang="en"> <he ...

  3. [BUUCTF][WEB][极客大挑战 2019]PHP 1

    打开靶机URL 看到字面提示 因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯不愧是我!!! 说明该网站有备份,说不定放在了Http服务器的某个目录下 那么这里我们可以用dirsearc ...

  4. requests请求超时尝试重连的3种方式

    参考文档 https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#module-urllib3.util.retry ...

  5. 02-Redis系列之-架构和高级API的使用

    通用部分 通用命令 # 1-keys # 打印出所有key keys * # 打印出所有以n开头的key keys n* # 打印出所有以nam开头,第四个字母是a到z的范围 keys nam[a-z ...

  6. Python函数每日一讲 - 一文让你彻底掌握Python中的frozenset函数

    引言 在 Python 中,frozenset() 函数是一个重要的工具,用于创建不可变的集合对象.本文将介绍 frozenset() 函数的语法.用法示例以及实际应用场景,帮助大家更好地理解和应用这 ...

  7. 使用二进制重排 & Clang插桩技术点来进行iOS冷启动进行优化

    1.冷启动 1.1 什么是冷启动? 冷启动是指内存中不包含该应用程序相关的数据,必须要从磁盘载入到内存中的启动过程. 注意:重新打开 APP, 不一定就是冷启动. 当内存不足,APP被系统自动杀死后, ...

  8. C++ 多线程笔记2 线程同步

    C++ 多线程笔记2 线程同步 并发(Concurrency)和并行(Parallelism) 并发是指在单核CPU上,通过时间片轮转的方式,让多个任务看起来像是同时进行的.实际上,CPU在一个时间段 ...

  9. Java运行时生成类元数据,初始化注解信息的方式

    问题前因 在一次技术升级中, 把分布式配置中心组件由百度的Disconf 改成 Nacos , 在对项目进行改造时, 首先将所有Disconf客户端依赖全部移除后, 依赖的封装的jar包中, 所有依赖 ...

  10. Java this关键字使用 详解+ 证明

    1 package com.bytezero.thistest; 2 /** 3 * 4 * @Description 5 * @author Bytezero·zhenglei! Email:420 ...