0

每当我在代码中使用 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);
}
4

1 回答 1

4

您有两个严重的错误:一个会导致数组越界写入,另一个可能会导致该错误。

第一,一定的越界写作,在parseString函数中。首先你有cmd变量的声明:

char *cmd[1];

这定义cmd一个元素的数组。然后你做

cmd[0] = token;
cmd[1] = NULL;

它写入单元素数组的两个元素。越界写入会导致未定义的行为

第二个错误在execute函数中,也是我在第一条评论中谈到的那个。你有

char bin[10] = "/bin/";

这定义bin为一个由十个字符组成的数组,并且您填写其中的六个(不要忘记字符串终止符)。在你做的子进程中

strcat(bin, cmd[0]);

它附加到字符串 incmd[0]到字符串 in bin。这里的问题是bin只有十个字符的空间,其中六个已经使用(如上所述)。这意味着只剩下四个字符的空间。如果命令比那个长,你也会越界并再次出现未定义的行为

第一个错误的解决方案很简单,创建cmd一个包含两个元素的数组。第二个错误的解决方案是要么bin增大,要么连接的数量不超过数组的容量;或者动态分配数组(不要忘记终止符的空间)。

您的代码还有很多其他潜在问题,例如args. 并且您并没有真正解析函数中的parseString参数,每个参数都被视为一个单独的命令。并且内存泄漏的情况下有分号分隔的“命令”。或者您不在任何需要的地方检查或处理错误。errno即使没有错误,您也可以使用它。

于 2018-03-18T04:04:10.237 回答