请帮我弄清楚以下代码片段的错误,该代码片段来自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
。
答案 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 。在这里,它不会有太大的区别,但在其他情况下它是好的,而不是抱怨。