fork() return 值错误
fork() return value bug
在下面的程序中,我在调用 fork 并将 return 值分配给 childpid 时错误地引入了一个错误(第 18 行)。
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 int main(){
8
9 int fd[2], nbytes;
10 pid_t childpid = -1;
11 char string[] = "Hello, world!";
12 char readbuffer[80];
13
14 pipe(fd);
15 printf("Parent: Beginning of Program...\n");
16
17
18 if(childpid = fork() == -1){ // BUG-FIX: Missing parenthesis (childpid=fork())==-1
19 printf("childpid == -1\n");
20 perror("fork");
21 exit(1);
22 }
23 if(childpid == 0){
24 // child process closes up input of pipe
25 close(fd[0]);
26
27 // send string through output side of pipe
28 write(fd[1], string, (strlen(string)+1));
29 printf("Child %d: Finished writing to pipe!\n",childpid);
30 exit(0);
31 }
32 else{
33 // parent closes output side of pipe
34 close(fd[1]);
35
36 // read in a string from the pipe
37 nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
38 printf("Parent %d: Received string: %s\n", childpid,readbuffer);
39 }
40
41
42 printf("Parent %d: End of program\n", childpid);
43 return 0;
44 }
错误的输出是:
$ ./a.exe
Parent: Beginning of Program...
Child 0: Finished writing to pipe!
运行 多次,我注意到 else 块从未到达。这意味着 childpid 从未在父进程中被分配一个 > 0 的值。这很奇怪,因为 childpid 最初被初始化为 -1,fork 确实发生了(这就是为什么 childpid 在子进程中的值为 0 的原因)但是父进程的 childpid 的值从来没有 > 0 - 这是为什么?
解决方法当然是用括号将赋值括起来,输出为:
$ ./a
Parent: Beginning of Program...
Parent 106648: Received string: Hello, world!
Child 0: Finished writing to pipe!
Parent 106648: End of program
我知道修复方法,但我有点不清楚如何向自己解释错误代码的输出!为什么childpid在子进程中是0,而在父进程中不是正值?
在有bug的版本中,你写了
if(childpid = fork() == -1)
这首先测试 fork()
的 return 值是否为 -1。通常情况下,它不会(分叉成功),因此它的计算结果为 false。假值为 0。然后将此 0 分配给 childpid
。程序继续到第23行:
if(childpid == 0){
在这种情况下 childpid
将始终为 0,因此此块始终会执行,永远不会到达下面的 else 块。
if
语句测试某项是否为零(假)或 non-zero(真)。例如:
if ( 0 ) {
是有效的语法,该块永远不会被执行。另一方面,
if ( 1 ) {
也是有效的,会一直执行。
if(childpid = fork() == -1){
相当于:
if(childpid = (fork() == -1) ){
由于 operator precedence。 ==
(比较)的优先级高于 =
(赋值)。
所以 childpid
在 两个 进程中将是 0
除非 fork() 失败(在这种情况下,childpid
将是 [=两个进程中的 18=] 和 if
块将永远不会被执行)。因此,else
块永远不会执行。
我不太喜欢在 if
语句中使用赋值。我更喜欢将它写在单独的一行中,这样我就不必一直在脑海中记住运算符的优先级了:
childpid = fork();
if(childpid == -1){
/* error */
}
if ( childpid == 0) {
...
}
else {
..
}
在下面的程序中,我在调用 fork 并将 return 值分配给 childpid 时错误地引入了一个错误(第 18 行)。
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 int main(){
8
9 int fd[2], nbytes;
10 pid_t childpid = -1;
11 char string[] = "Hello, world!";
12 char readbuffer[80];
13
14 pipe(fd);
15 printf("Parent: Beginning of Program...\n");
16
17
18 if(childpid = fork() == -1){ // BUG-FIX: Missing parenthesis (childpid=fork())==-1
19 printf("childpid == -1\n");
20 perror("fork");
21 exit(1);
22 }
23 if(childpid == 0){
24 // child process closes up input of pipe
25 close(fd[0]);
26
27 // send string through output side of pipe
28 write(fd[1], string, (strlen(string)+1));
29 printf("Child %d: Finished writing to pipe!\n",childpid);
30 exit(0);
31 }
32 else{
33 // parent closes output side of pipe
34 close(fd[1]);
35
36 // read in a string from the pipe
37 nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
38 printf("Parent %d: Received string: %s\n", childpid,readbuffer);
39 }
40
41
42 printf("Parent %d: End of program\n", childpid);
43 return 0;
44 }
错误的输出是:
$ ./a.exe
Parent: Beginning of Program...
Child 0: Finished writing to pipe!
运行 多次,我注意到 else 块从未到达。这意味着 childpid 从未在父进程中被分配一个 > 0 的值。这很奇怪,因为 childpid 最初被初始化为 -1,fork 确实发生了(这就是为什么 childpid 在子进程中的值为 0 的原因)但是父进程的 childpid 的值从来没有 > 0 - 这是为什么?
解决方法当然是用括号将赋值括起来,输出为:
$ ./a
Parent: Beginning of Program...
Parent 106648: Received string: Hello, world!
Child 0: Finished writing to pipe!
Parent 106648: End of program
我知道修复方法,但我有点不清楚如何向自己解释错误代码的输出!为什么childpid在子进程中是0,而在父进程中不是正值?
在有bug的版本中,你写了
if(childpid = fork() == -1)
这首先测试 fork()
的 return 值是否为 -1。通常情况下,它不会(分叉成功),因此它的计算结果为 false。假值为 0。然后将此 0 分配给 childpid
。程序继续到第23行:
if(childpid == 0){
在这种情况下 childpid
将始终为 0,因此此块始终会执行,永远不会到达下面的 else 块。
if
语句测试某项是否为零(假)或 non-zero(真)。例如:
if ( 0 ) {
是有效的语法,该块永远不会被执行。另一方面,
if ( 1 ) {
也是有效的,会一直执行。
if(childpid = fork() == -1){
相当于:
if(childpid = (fork() == -1) ){
由于 operator precedence。 ==
(比较)的优先级高于 =
(赋值)。
所以 childpid
在 两个 进程中将是 0
除非 fork() 失败(在这种情况下,childpid
将是 [=两个进程中的 18=] 和 if
块将永远不会被执行)。因此,else
块永远不会执行。
我不太喜欢在 if
语句中使用赋值。我更喜欢将它写在单独的一行中,这样我就不必一直在脑海中记住运算符的优先级了:
childpid = fork();
if(childpid == -1){
/* error */
}
if ( childpid == 0) {
...
}
else {
..
}