You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

stdout重定向到管道时execlp出现异常行为的原因排查

execlp启动ls输出异常的问题分析

问题描述

我尝试将通过execlp启动的程序输出读取到缓冲区,以下是我的代码:

void do_ls_la_buf() {
    int piped[2];
    if(pipe(piped) == -1) {
        printf("Couldn't initiate pipe\n");
        exit(EXIT_FAILURE);
    }

    if(fork() == 0) {
        close(piped[0]);    // close read end of child
        dup2(piped[1], 1);  // stdout to pipe
        dup2(piped[1], 2);  // stderr to pipe
        close(piped[1]);

        execlp("/usr/bin/ls", "ls", "-la");
    }
    else {
        char buf[1024] = "";
        close(piped[1]);    // close write end of parent

        while(read(piped[0], buf, sizeof(buf))) {
            printf("Read from pipe %d chars: %s\n", strlen(buf), buf);
        }
    }
}

int main {
    do_ls_la_buf();
    wait(NULL);
}

运行后得到如下输出:

Read from pipe 22 chars: ls: cannot access 'H='
Read from pipe 28 chars: : No such file or directory

由于execlp的参数是硬编码的,我对此结果感到困惑,想知道这是怎么回事?

问题原因与修复

核心问题:main函数签名错误

你的main函数定义不符合C语言标准,正确的签名应该是int main(void)或int main(int argc, char *argv[]),而你写的int main {缺少括号和参数列表,这会导致编译器解析错误,破坏程序栈结构,使得execlp调用时的参数被意外覆盖,最终让ls接收到非法参数(比如H=),触发"找不到文件"的错误。

修复步骤

  1. 修正main函数的签名:
int main(void) {
    do_ls_la_buf();
    wait(NULL);
    return 0; // 补充符合标准的返回值
}
  1. 优化管道读取逻辑(可选但更安全):
    当前用strlen(buf)统计读取长度存在风险,若读取内容不含字符串终止符,strlen会越界。应直接使用read的返回值,并手动添加终止符:
else {
    char buf[1024];
    close(piped[1]);
    ssize_t n;
    while((n = read(piped[0], buf, sizeof(buf)-1)) > 0) {
        buf[n] = '\0'; // 确保字符串终止
        printf("Read from pipe %zd chars: %s\n", n, buf);
    }
}

修改后程序即可正常执行ls -la并正确读取输出。

内容的提问来源于stack exchange,提问作者BaridunDuskhide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:42:24