【发布时间】:2018-03-18 02:32:11
【问题描述】:
每当我在我的代码中使用 execv() 时,它都可以正常工作并且没有错误,但仍然会导致堆栈粉碎导致程序在运行时崩溃。我在这里做错什么了吗? 这是带有 execv() 的函数:
void execute(char *args[], char *cmd[])
{
pid_t pid;
int status;
char bin[10] = "/bin/";
pid = fork();
// child process
if(pid == 0)
{
strcat(bin, cmd[0]);
execv(bin, args);
} else{
perror("error");
while(wait(&status) != pid);
}
}
这是我从中获取 args 和 cmd 的地方。会不会是我在这里做的事情造成的?
void parseString(char *command)
{
char **args = malloc(sizeof(char*) * 16);
int i = 0;
int j = 0;
char *cmd[1];
// split each command by semicolons if necessary, then send each sub command to parseString()
if(strchr(command, ';')) {
char *semi_token = strtok(command, ";");
while(semi_token != NULL){
args[i] = semi_token;
semi_token = strtok(NULL, " ");
parseString(args[i]);
i++;
}
} else {
// if no semi colons, split the commandby spaces and call execute() using the args and cmd
char *token = strtok(command, " ");
while(token != NULL)
{
args[i] = token;
args[++i] = NULL;
while(j == 0 && token != NULL) {
cmd[0] = token;
cmd[1] = NULL;
j++;
}
token = strtok(NULL, " ");
}
execute(args, cmd);
}
j = 0;
i = 0;
free(args);
}
函数调用发生在这里。命令是用户从标准输入输入的。只需要位于/bin/ 中的基本命令。类似 ls -l 或 cat 文件。
while(1){
command = getCommand();
parseString(command);
}
【问题讨论】:
-
在你的
execute函数中,cmd[0]的内容是什么?它会超过四个字符吗?因为这就是bin的全部内容。 -
而且你只限制了 15 个参数,你有超过 15 个参数吗?
-
总是在父级中调用
perror("error");是错误的。可以说,您应该检测pid == -1(或pid < 0)然后报告错误是合适的。您没有展示如何调用代码,也没有解释您提供的输入内容。您通常没有创建 MCVE (minimal reproducible example),因此很难看到您在做什么。但是你在你的execute()函数中过于简洁——char bin[100] = "/bin/";可能会更好,但并不是每个命令都在/bin中(有/usr/local/bin,有时/usr/bin与/bin是分开的)。 -
顺便说一句,不要忘记
execv也可能失败。而在你当前的计划中,发生的事情可能比你想象的要多,并导致坏事。 -
或者在
execv后面加一个exit(1),这样子进程在execv失败后退出。
标签: c stack-smash