进程间Pipe实现字符串大写转换程序故障排查求助
问题排查与修复方案
你的管道程序无法正常工作,核心问题并非子进程提前读取,而是代码中存在多处逻辑错误和未定义行为,以下是具体问题和修复步骤:
1. 父进程写入循环的未初始化变量与逻辑错误
- 问题:父进程中
int n;未初始化就进入while(n < len)循环,触发未定义行为,程序可能直接跳过写入逻辑。同时循环条件错误,应判断已写入总字节数total是否小于需要写入的长度len,而非单次写入的n。 - 修复:初始化
n = 0,修改循环条件为while(total < len),且每次写入剩余未发送的字节:
int n = 0; int total = 0; while(total < len) { n = write(fd[1], buffer + total, len - total); if(n < 0) { perror("FEHLER BEIM SENDEN\n"); break; } total += n; }
2. 父进程未关闭管道写端
- 问题:父进程写完数据后未关闭
fd[1],导致子进程的read会一直阻塞等待更多数据(管道写端仍处于打开状态)。 - 修复:写入完成后调用
close(fd[1]);。
3. 子进程未检查read返回值
- 问题:子进程的
read未判断返回值,当管道写端关闭后,read返回0表示无更多数据,但当前代码会继续读取,导致c值不确定,可能陷入无限循环或处理垃圾值。 - 修复:读取时检查
read返回值:
ssize_t ret; while(1) { ret = read(fd[0], &c, 1); if(ret <= 0) { // 返回0表示写端关闭,-1表示出错 break; } if(c == '\0') { break; } if(isalpha(c)) { // 判断字母,需包含<ctype.h> buffer[i] = c; i++; } }
4. 子进程字符判断逻辑错误
- 问题:
c > 64 || c < 123会匹配所有ASCII字符(所有ASCII字符都满足大于64或小于123),起不到过滤字母的作用。 - 修复:使用
isalpha(c)(需包含<ctype.h>),或直接判断(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')。
5. 子进程buffer未初始化
- 问题:
buffer由malloc分配,初始为垃圾数据,后续处理可能输出无效值。 - 修复:子进程读取前初始化buffer:
memset(buffer, 0, BUF);
6. 子进程遍历buffer的效率问题
- 问题:处理和输出时遍历整个
BUF长度,但实际仅读取了i个有效字符,多余遍历会处理空值或垃圾值。 - 修复:循环到
i即可,避免变量名冲突:
for(int j = 0; j < i; j++) { if(buffer[j] >= 'a' && buffer[j] <= 'z') { buffer[j] -= 32; } } // 输出同理 for(int j = 0; j < i; j++) { printf("%c ", buffer[j]); }
完整修正代码
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <string.h> #include <ctype.h> #define BUF 64 /* 任务: 父进程:通过pipe将包含大小写字母的数组传递给子进程 子进程:将所有字符转换为大写 */ int main(void) { pid_t pid; int fd[2]; if(pipe(fd) == -1) { perror("FEHLER BEIM ERSTELLEN DER PIPE\n"); exit(EXIT_FAILURE); } char *buffer = malloc(sizeof(char)*BUF); if(buffer == NULL) { perror("FEHLER BEIM SPEICHERANFORDERUNG\n"); exit(EXIT_FAILURE); } switch(pid = fork()) { case -1: perror("FEHLER BEI FORK\n"); free(buffer); close(fd[0]); close(fd[1]); exit(EXIT_FAILURE); case 0: //子进程 close(fd[1]); memset(buffer, 0, BUF); char c; int i = 0; ssize_t ret; while(1) { ret = read(fd[0], &c, 1); if(ret <= 0) { break; } if(c == '\0') { break; } if(isalpha(c)) { buffer[i] = c; i++; if(i >= BUF-1) { break; } } } close(fd[0]); for(int j = 0; j < i; j++) { if(buffer[j] >= 'a' && buffer[j] <= 'z') { buffer[j] -= 32; } } printf("Die Zeichen in Großbuchstaben sind:\n\n"); for(int j = 0; j < i; j++) { printf("%c ", buffer[j]); } printf("\n"); free(buffer); exit(EXIT_SUCCESS); default: //父进程 close(fd[0]); char string1[] = "a b c d e f G h I"; memset(buffer, 0, BUF); strcpy(buffer, string1); int len = strlen(buffer) + 1; int n = 0; int total = 0; while(total < len) { n = write(fd[1], buffer + total, len - total); if(n < 0) { perror("FEHLER BEIM SENDEN\n"); break; } total += n; } close(fd[1]); printf("Nachricht gesendet.\n"); free(buffer); wait(NULL); exit(EXIT_SUCCESS); } }
内容的提问来源于stack exchange,提问作者Chanyoung Woo
相关产品推荐
相关产品推荐

