这个代码来自APUE有什么问题?

时间:2017-07-30 00:49:41

标签: c linux

请帮我弄清楚以下代码片段的错误,该代码片段来自APUE第8.6节(W Richard Stevens,Stephen A Rago Advanced Programming in the Unix Environment, 3rd Edn):

#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if ( pid == 0) {
        if ((pid == fork()) < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (pid > 0)
            exit(0);

        sleep(2);
        printf("second child, parent pid = %ld \n", (long)getppid());
        fflush(stdout);
        exit(EXIT_SUCCESS);
    }

    if (waitpid(pid, NULL, 0) != pid) {
        perror("waitpid");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

APUE书的结果是:

$ ./a.out
$ second child, parent pid = 1

父亲fork第一个孩子,第一个孩子fork第二个孩子,第一个孩子退出。所以第二个孩子的父母将是init。但是,在我的Ubuntu 16.04上,结果是:

second child, parent pid = 8078
second child, parent pid = 8077

父亲fork第一个孩子,第一个孩子fork第二个孩子,第一个孩子退出。所以第二个孩子的父母将是init

1 个答案:

答案 0 :(得分:4)

将评论转移到答案。

问题是签名过多=

 if ((pid == fork()) < 0) {

你需要:

 if ((pid = fork()) < 0) {

我的编译器告诉我:

error: comparison of constant ‘0’ with boolean expression is always false [-Werror=bool-compare]

如果你没有收到警告,你没有使用足够的警告选项,或者你使用过于古老的GCC版本。在Mac上运行macOS Sierra 10.12.6的Mine的GCC 7.1.0 - 编译选项:

gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    -Wstrict-prototypes fk47.c -o fk47

包含您的代码的源文件fk47.c。我还抱怨您main不是int main(void)

在我看来,如果不使用接近我使用的选项,你就无法编译;你会错过太多简单的错误。请记住,C编译器比你更了解C语言,如果你这样做,它会告诉你你做错了什么。

另外,mike bayko asked

  

为什么不使用return 0(或1)退出main函数?

基本答案是“因为这不是书的作用”。当代码位于return时,我更喜欢main中的main(),但代码通常会迁移到main()以外的函数,然后exit() - 或其中一个它的快速变体 - 变得相关。

also

  

为什么要在if声明中进行分配?如果您想查看是否pid < 0,那么您应该在if语句的条件之外指定pid = fork();

如果准确编码,在if语句中执行赋值没有问题,并且使用赋值可以防止代码在if (…) … else if (…) … else if (…) …个长链操作中脱离页面的RHS 。在这里,它不会有太大的区别,但在其他情况下它是好的,而不是抱怨。