Windows控制台C程序管道运行时出现管道破裂错误求助
Windows控制台C程序管道运行时出现管道破裂错误求助
嘿,我来帮你排查这个问题!你的程序手动输入时正常,但通过管道接收其他命令输出就报“Broken pipe”,核心是代码里有几个关键错误,咱们一步步拆解来看:
最致命的错误:fclose参数完全用错了
你代码最后一行的fclose("tmpstdin.txt");是彻底的错误!fclose要求接收的是FILE*类型的指针(也就是你之前打开的fp变量),而不是文件名字符串。这个错误会直接导致程序资源清理逻辑崩溃,在管道这种依赖进程间资源状态的场景下,就会触发“Broken pipe”错误。
管道场景下的逻辑与资源问题
你的循环停止条件while (fgets(s, BUFLEN, stdin) != NULL && *s != '\n')是符合需求的(空行或EOF停止),但在管道场景中,前序命令(比如dir /B)的输出没有空行结尾,程序读完所有输入后循环正常结束,但因为fclose的错误,后续的文件操作和退出时的资源清理彻底混乱,直接放大了管道相关的状态异常。
另外还有几个潜在的小问题:
- 用
calloc分配的内存没有free,会造成内存泄漏 - 写入临时文件的循环中,
fputs出错break后没有及时处理错误 - 部分资源(比如打开的文件)在中途出错时没有及时关闭,导致资源泄漏
修正后的完整代码
我把所有问题都修复了,你可以直接测试:
#include <stdio.h> #include <stdlib.h> #define BUFLEN 80 int main(int argc, char *argv[]) { char *s; FILE *fp; fp = fopen("tmpstdin.txt", "w+"); if (fp == NULL) { fputs("File I/O error: Cannot create file.\n", stderr); exit(-1); } s = calloc(BUFLEN, sizeof (*s)); if (s == NULL) { fputs("Memory allocation error.\n", stderr); fclose(fp); // 分配失败先关闭已打开的文件 exit(-1); } // 读取stdin到临时文件,直到空行或EOF while (fgets(s, BUFLEN, stdin) != NULL) { if (*s == '\n') { // 遇到空行直接终止读取 break; } if (fputs(s, fp) == EOF) { fputs("File I/O error: Cannot write to file.\n", stderr); free(s); fclose(fp); exit(-1); } } // 检查stdin的读取错误 if (ferror(stdin) != 0) { fputs("I/O error on stdin.\n", stderr); free(s); fclose(fp); exit(-1); } // 回卷临时文件指针到开头 rewind(fp); // 读取临时文件内容输出到stdout while (fgets(s, BUFLEN, fp) != NULL) { if (fputs(s, stdout) == EOF) { fputs("I/O error on stdout.\n", stderr); free(s); fclose(fp); exit(-1); } } // 检查临时文件的读取错误 if (ferror(fp)) { fputs("File I/O error: Cannot read from file.\n", stderr); free(s); fclose(fp); exit(-1); } // 正确释放资源:先释放内存,再关闭文件 free(s); fclose(fp); return 0; }
修正后管道场景正常的原因
- 核心修复了
fclose的参数错误,现在用正确的FILE*指针关闭文件,资源清理逻辑正常 - 补充了全流程的资源释放逻辑,避免内存泄漏和文件句柄泄漏
- 增强了错误处理分支,每一步出错都能先清理资源再退出,不会因为资源异常导致管道状态崩溃
你把修正后的代码编译后,再用dir /B | foo.exe测试,应该就不会出现“Broken pipe”错误了!
内容来源于stack exchange




