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

C/C++编写Shell调用chdir切换目录后出现卡顿与命令执行报错问题

问题根因分析
  • 逻辑顺序错误:fork操作放在了内置命令cd的判断之前,每次输入cd命令都会额外创建一个子进程,子进程没有正常退出,会和父进程同时抢占终端输入,导致输入内容被拆分、程序卡顿、命令执行报错只显示部分字符。
  • cd命令判断逻辑错误:readline返回的输入字符串默认不带末尾换行符,你使用strncmp(command[0], "cd\n", 2)做判断,仅匹配前2个字符会导致所有以cd开头的字符串都被误识别为cd命令,且不需要匹配换行符。
  • 资源泄漏:cd分支执行continue跳转下一轮循环前,没有释放input和command的堆内存,长期运行会导致内存泄漏。
  • 子进程退出逻辑缺失:execvp执行失败后子进程没有主动退出,会继续进入主循环抢占终端输入。
  • cd参数边界缺失:未处理用户仅输入cd不带参数的场景,直接访问command[1]会触发空指针访问段错误。
  • 头文件缺失:代码使用了strtok、strcmp等C字符串处理函数,但未引入<string.h>头文件,部分编译器下会出现隐式声明报错。
修复方案

调整代码逻辑顺序,先处理内置命令再处理外部命令,修正判断条件和退出逻辑,修复后的完整代码如下:

#include <stdio.h>
#include <readline/readline.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <string>

#define clear() printf("\033[H\033[J")

char** getInput(char* input)
{
  char** command = (char**) malloc(8 * sizeof(char*));
  const char* separator = " ";
  char* parsed;
  int index = 0;

  parsed = strtok(input, separator);
  while (parsed != NULL)
    {
      command[index] = parsed;
      index++;
      parsed = strtok(NULL, separator);
    }
  command[index] = NULL;
  return command;
}

int main()
{
  char** command;
  char* input;
  pid_t child_pid;
  int stat_loc;

  bool loop = true;
  do
    {
      input = readline("");
      // 空输入直接跳过
      if (!input || !*input) {
        free(input);
        continue;
      }
      command = getInput(input);
      // 先处理内置命令cd,不需要fork
      if (strcmp(command[0], "cd") == 0)
        {
          const char* target_dir = command[1];
          // 不带参数默认切换到HOME目录
          if (!target_dir) {
            target_dir = getenv("HOME");
          }
          if (chdir(target_dir) < 0) {
            printf("Couldn't execute cd to: %s\n", target_dir);
          }
          // 处理完释放资源
          free(input);
          free(command);
          continue;
        }
      // 外部命令才fork执行
      child_pid = fork();
      if (child_pid < 0)
        {
          printf("Fork Failed\n");
          free(input);
          free(command);
          exit(EXIT_FAILURE);
        }
      if (child_pid == 0)
        {
          execvp(command[0], command);
          printf("couldn't execute: %s\n", command[0]);
          // 子进程执行失败必须退出,避免继续跑主逻辑
          exit(EXIT_FAILURE);
        }
      else {
        waitpid(child_pid, &stat_loc, WUNTRACED);
      }
      free(input);
      free(command);
    } while (loop);
  return 0;
}

编译指令保持不变:g++ main.cc -lreadline

内容的提问来源于stack exchange,提问作者Anirudh Yamunan Govindarajan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:24:01