You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

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;
}

修正后管道场景正常的原因

  1. 核心修复了fclose的参数错误,现在用正确的FILE*指针关闭文件,资源清理逻辑正常
  2. 补充了全流程的资源释放逻辑,避免内存泄漏和文件句柄泄漏
  3. 增强了错误处理分支,每一步出错都能先清理资源再退出,不会因为资源异常导致管道状态崩溃

你把修正后的代码编译后,再用dir /B | foo.exe测试,应该就不会出现“Broken pipe”错误了!

内容来源于stack exchange

火山引擎 最新活动