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

自定义Shell执行命令后触发Seg Fault且管道功能失效问题求助

自定义Shell问题修复方案

1. 核心段错误问题

问题根因

  • exec_cmd函数内存释放逻辑位置错误:你将cmd_seg链表的释放代码写在了遍历命令段的for循环内部,第一次执行完第一个命令段就会把整个链表全部释放,后续for循环执行cur = cur->next时会访问已释放的野指针,直接触发段错误。
  • readLine函数未补字符串结束符:读取输入存入缓冲区后,遇到换行或EOF直接返回,未在缓冲区末尾写入\0,后续strlen、strtok等字符串操作全部越界访问内存。
  • 子进程执行失败未退出:exec_cmd_seg中execvp执行失败后,子进程没有调用exit退出,会继续运行父进程的逻辑,导致内存重复释放、逻辑混乱。

修复方法

  1. 将exec_cmd中释放cmd_seg链表的代码移到for循环外部,等所有命令段执行完成后再释放:
int exec_cmd(struct cmd *command){
    int status = 1;
    struct cmd_seg* cur;
    struct cmd_seg* pfree;
    int fd = 0;
    for(cur = command->root; cur != NULL; cur = cur -> next){
        if(cur -> next){
            int fd2[2];
            pipe(fd2);
            status = exec_cmd_seg(cur, fd, fd2[1], command->mode, 0);
            fd = fd2[0];
        }
        else{
            status = exec_cmd_seg(cur, fd, 1, command->mode, 0);
        }
    }
    // 释放逻辑移到循环外部
    cur = command -> root;
    pfree = cur;
    while(cur != NULL){
        cur = cur -> next;
        free(pfree);
        pfree = cur;
    }
    free(command);
    return status;
}
  1. 修改readLine函数,返回缓冲区前补结束符:
if(ch == EOF || ch == '\n'){
    buffer[pos] = '\0'; // 新增结束符写入
    printf("Command: %s\n", buffer);
    return buffer;
}
  1. exec_cmd_seg中execvp失败后加退出逻辑:
int result = execvp(segment->args[0], segment->args);
if(result < 0){
    printf("\nError Executing Command: %s", segment->args[0]);
    exit(EXIT_FAILURE); // 新增子进程退出逻辑
}

2. 管道功能异常问题

问题根因

  • 文件描述符关闭逻辑错误:exec_cmd_seg中关闭文件描述符用了else if判断,当in_fd和out_fd都不是标准输入输出时(管道场景),out_fd不会被关闭,管道读端收不到EOF,会一直卡住。
  • 单命令段等待逻辑不适用管道:exec_cmd_seg中每启动一个子进程就立刻waitpid,如果前一个命令的输出超过管道缓冲区,会因为没有读端读取导致写阻塞,整个管道卡死。
  • 内置命令返回值判断逻辑冗余:exec_cmd_seg中判断IsBuiltin == 0才返回,但builtins函数只会返回1或者-1,该判断永远不触发,逻辑混乱。

修复方法

  1. 修改exec_cmd_seg的文件描述符关闭逻辑,去掉else if改为独立判断:
if(in_fd != 0){
    close(in_fd);
}
if(out_fd != 1){ // 去掉else,改为独立判断
    close(out_fd);
}
  1. 调整管道场景的等待逻辑:所有管道段的子进程全部fork启动完成后,再统一调用waitpid回收所有子进程,不要启动一个等一个。
  2. 修正内置命令判断逻辑:
int IsBuiltin = builtins(segment);
if(IsBuiltin == 1){ 
    return 1; 
}
// 后续为外部命令执行逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:09:02