循环读取输入时buf残留旧值:C语言命令行程序调试求助
问题根源与修复方案
核心问题原因
read() 不自动添加字符串结束符
read() 仅将字节从标准输入复制到buf,不会自动在末尾追加'\0'。当后续输入的长度小于之前的输入时,buf中未被覆盖的旧字节会保留,而printf、strlen等函数依赖'\0'判断字符串结束,因此会读取到残留的旧内容。换行处理逻辑错误
原代码用buf[strlen(buf)-1] = '\0'去掉换行,但strlen(buf)的计算依赖buf中已有的'\0'。如果read后没有手动添加'\0',strlen会越界读取内存,导致结果不可靠,甚至触发未定义行为。字符串比较方式错误
if (buf == "exit")是比较指针地址而非字符串内容,永远不会匹配成功,应该用strcmp(buf, "exit") == 0。execvp 参数数组未以NULL结尾
execvp要求参数数组的最后一个元素必须是NULL,否则会读取内存中随机数据,导致执行失败。冗余的命令行参数循环
原代码中的argc++和外层for (int i=1; i<argc; i++)完全无意义,会导致重复fork,与用户输入的终端命令处理逻辑无关。
修复后的代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <fcntl.h> #include <string.h> #define BUFFERSIZE 1024 int main(int argc, char* argv[]) { char buf[BUFFERSIZE]; int n; printf("Please enter commands: \n"); // 读取时预留一个字节给'\0',防止越界 while ((n = read(STDIN_FILENO, buf, BUFFERSIZE - 1)) > 0) { // 手动添加字符串结束符,确保字符串函数能正确识别边界 buf[n] = '\0'; // 安全处理换行符:若最后一个字符是'\n',替换为'\0' if (n > 0 && buf[n-1] == '\n') { buf[n-1] = '\0'; } printf("original string: %s:\n", buf); int i = 0; char* array[100]; char* token1 = strtok(buf, " "); while (token1 != NULL) { array[i++] = token1; token1 = strtok(NULL, " "); } // 给execvp添加NULL结尾,满足函数要求 array[i] = NULL; for (int j = 0; j < i; j++) { printf("Array value %d: %s:\n", j, array[j]); } // 正确比较字符串内容 if (strcmp(buf, "exit") == 0) { printf("found it\n"); break; // 匹配到exit则退出循环 } pid_t pid; if ((pid = fork()) < 0) { perror("fork"); } else if (pid == 0) { // 子进程执行命令 if (execvp(array[0], array) == -1) { perror("execvp"); return EXIT_FAILURE; } } else { // 父进程等待子进程结束 int status; wait(&status); printf("Please enter commands again: \n"); } } if (n == -1) perror("read"); return 0; }
关键修复点说明
- 读取时预留一个字节给
'\0',避免添加结束符时越界。 - 每次read后立即添加
'\0',确保字符串函数能正确识别边界。 - 通过判断buf[n-1]是否为
'\n'来处理换行,避免依赖不可靠的strlen结果。 - 给参数数组添加NULL结尾,满足execvp的调用要求。
- 用strcmp替换指针比较,正确判断字符串内容是否匹配。
- 移除冗余的argc操作和循环,确保每次输入只处理一次命令。
内容的提问来源于stack exchange,提问作者sgrandom
相关产品推荐
相关产品推荐

