C语言子进程菜单选项读取异常问题求助
子进程菜单重复输出问题解决
我正在编写一个涉及子进程的C程序,程序内置菜单选项供用户选择不同方式调用子进程,但菜单读取功能异常——输入选项后菜单会重复输出两次,不符合预期。
程序代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/wait.h> #include <locale.h> #include <string.h> #include <math.h> extern char **environ; int main(int argc, const char *argv[], char *env[]) { char **name; int x = 0, num; pid_t pid; for(num=0; ; num++) // 统计环境变量个数 if(env[num] == NULL) break; name = (char **) calloc(1, sizeof(char *)); if(!name) { printf("\nMemory isn't allocated"); return -1; } name[0] = (char *) calloc(9, sizeof(char)); if(!name[0]) { printf("\nMemory isn't allocated"); return -1; } // 修复笔误:args未定义,改为env for(int i=0; i<num; i++) fprintf(stdout, "%s\n", env[i]); fprintf(stdout, "Parent process's started...\n"); char *temp; temp = (char *) calloc(12, sizeof(char)); if(!temp) { printf("\nMemory isn't allocated"); return -1; } while(x < 100) { sprintf(temp, "%d", x); strcpy(name[0], "child_"); strcat(name[0], temp); puts("path info: +-using getenv()"); puts(" *-scanning array of environment parameters"); puts(" &-using environ"); puts(" q-end"); switch(getchar()) { case '+': printf("PLUS:\n"); pid = fork(); if(pid == -1) { fprintf(stdout, "Error, code - %d\n", errno); } else if(pid == 0) { // 子进程执行execve,失败则立即退出 execve("./child", name, env); perror("execve failed"); exit(EXIT_FAILURE); } break; case '*': printf("ASTERISK\n"); pid = fork(); if(pid == -1) { fprintf(stdout, "Error, code - %d\n", errno); } else if(pid == 0) { execve(findPath(env, num), name, env); perror("execve failed"); exit(EXIT_FAILURE); } break; case '&': printf("AMPERSAND:\n"); pid = fork(); if(pid == -1) { fprintf(stdout, "Error, code - %d\n", errno); } else if(pid == 0) { execve(findPath(environ, num), name, env); perror("execve failed"); exit(EXIT_FAILURE); } break; case 'q': return 0; default: printf("Wrong parameter\n"); return -1; } // 父进程等待子进程结束后再继续 wait(NULL); // 清理输入缓冲区残留的换行符 while(getchar() != '\n' && !feof(stdin)); x++; } exit(0); }
实际运行输出
Parent process's started... path info: +-using getenv() *-scanning array of environment parameters &-using environ q-end + PLUS: path info: +-using getenv() *-scanning array of environment parameters &-using environ q-end path info: +-using getenv() *-scanning array of environment parameters &-using environ q-end q Program ended with exit code: 0
预期输出
Parent process's started... path info: +-using getenv() *-scanning array of environment parameters &-using environ q-end + PLUS: path info: +-using getenv() *-scanning array of environment parameters &-using environ q-end q Program ended with exit code: 0
问题根源及修复点
子进程execve失败后未退出
当execve调用失败(如目标程序不存在、权限不足),子进程不会被替换,会继续执行后续循环代码,导致父进程和子进程同时输出菜单。
修复:在子进程分支(pid == 0)的execve后添加错误处理,调用perror打印错误并exit终止子进程。父进程未等待子进程终止
父进程fork后直接进入下一次循环,此时子进程若仍在运行,会和父进程同时输出菜单。
修复:在每个case的break前调用wait(NULL),让父进程等待子进程结束后再继续。输入缓冲区残留换行符
用户输入选项后按下的回车会留在缓冲区,下一次getchar会读取该换行符,可能引发异常。
修复:在wait后添加循环清空缓冲区直到读取到换行符。代码笔误
原代码中args[i]未定义,需改为env[i]才能正常编译。fflush(stdin)的未定义行为
标准C中fflush仅对输出流有效,对输入流使用属于未定义行为,需删除该语句。
内容的提问来源于stack exchange,提问作者Nina
相关产品推荐
相关产品推荐

