C++编写自定义Shell执行多参数命令报exec: bad address错误
问题诊断
你遇到的两个报错分别对应代码中的三类错误:
- exec: bad address 错误根因:传给
execvp的参数数组存在越界写、终止符位置错误问题- 你定义的
args数组长度为argsBefore.size(),但循环条件写为i <= argsBefore.size(),数组有效下标范围是0 ~ size-1,循环到i=size时已经写入数组外的非法内存 - 你用
args[sizeof(args)+1] = NULL设置终止符的逻辑完全错误:sizeof(args)拿到的是栈数组的总字节数(64位系统下每个指针占8字节,比如3个参数的数组总长度24字节),不是数组元素个数,写入的位置完全是野内存。execvp要求参数数组必须以NULL指针作为最后一个元素,找不到终止符时会遍历到非法内存地址,直接触发bad address报错。
- 你定义的
- namespace: not found 错误根因:命令用错了
cpp是GCC的C预处理器程序,不是用来运行编译后二进制文件的命令,你用cpp去跑编译生成的可执行文件,它会把二进制当成C源码解析,自然会报莫名其妙的语法错误。 - 隐藏的兼容性问题:你写的
char* args[argsBefore.size()]是C99标准的可变长数组(VLA)特性,不属于标准C语法,仅靠g的非标准扩展支持,行为不稳定。
修复方案
按以下步骤修改代码即可解决问题:
- 替换错误的参数数组构造逻辑,不要用栈上可变长数组,改用
vector<char*>管理参数列表,避免越界:
把原代码中以下错误片段:
替换为:char* args[argsBefore.size()]; for(size_t i =0; i<=(argsBefore.size());i++){ args[i]=(char*)argsBefore[i].c_str(); } args[sizeof(args)+1]=NULL; // null terminated array for execvpstd::vector<char*> args; for (size_t i = 0; i < argsBefore.size(); i++) { // 过滤分割产生的空字符串,兼容多空格分隔的命令 if (!argsBefore[i].empty()) { args.push_back(const_cast<char*>(argsBefore[i].c_str())); } } args.push_back(nullptr); // 严格按照execvp要求,在参数列表末尾放空指针作为终止符 - 修改子进程中的
execvp调用,传入vector的底层数组指针:if (execvp(args[0], args.data()) == -1) { perror("exec"); exit(EXIT_FAILURE); } - 修正编译运行命令:
- 编译命令用g直接生成可执行文件,指定C标准避免扩展兼容问题:
g++ your_shell.cpp -o myshell -std=c++17 - 给生成的二进制加执行权限后直接运行,不要用cpp命令:
chmod +x myshell && ./myshell
- 编译命令用g直接生成可执行文件,指定C标准避免扩展兼容问题:
- 可选修复:
handleLogout函数中用cin >> eingabe读取输入后,会在输入缓冲区残留换行符,导致下一次getline读到空命令,在cin >> eingabe后加一行std::cin.ignore(1024, '\n');清空缓冲区即可。
内容的提问来源于stack exchange,提问作者Toubs202
相关产品推荐
相关产品推荐

