双指针作为 execvp() 的参数

Double pointer as argument to execvp()

我正在尝试使用自定义 **tokens 双指针作为输入来执行 execvp(),而不是 "create a custom shell" 赋值上的 argv[],如下所示:

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

int main(){
    char *token;
    char **tokens = malloc(sizeof(char*)*512); //512 is for the maximum input-command length
    char *command=malloc(sizeof(char)*512);
    int i = 0;
    pid_t child_pid;
    int status;
    //***********take input from user*************************************
    fgets(command,512,stdin);

    //***********parse input*********************************************
    token = strtok(command," \t");

    while( token != NULL ) {

        tokens[i]=token;
        i ++;
        token = strtok(NULL, " \t");

    }
    child_pid = fork();

    if(child_pid == 0) {
        /* This is done by the child process. */
        execvp(tokens[0], tokens);
    } else {
        waitpid(child_pid, &status, WUNTRACED);
    }
}

问题肯定出在这一行:

execvp(tokens[0], tokens);

我只是不明白为什么它不能执行并打印到我的 stdout。 我试过这个:

execvp("ls", tokens);

而且效果很好。 还有这个:

printf("%s\n", tokens[0]);

输出为(根据测试输入:ls):

ls

您需要使用sizeof(char *)分配内存。

char **tokens = malloc(sizeof(char *)*512);
                                   ^^----------->Size of char pointer

截至目前,您正在分配 sizeof(char) 从而调用未定义的行为。


还要考虑@n.m

指出的第一条评论

您的代码有几个问题,包括:

  1. 传递给 execvp() 的参数指针数组必须以空指针结尾。你不保证。

  2. 通过fgets 获得的字符串将包括所有字符直至并包括该行的换行符,如果缓冲区足够大以容纳它的话。您不在令牌定界字符中包含换行符,因此对于单字命令 ls,传递给 execvp() 的命令等同于 "ls\n" 而不是 "ls"ls\n 不太可能(但并非不可能)是您计算机上可用的命令。

  3. 您不检查 execvp() 或任何其他函数的 return 值,也不处理任何错误。 execvp() 的特殊之处在于它 return 仅在出现错误时才会出现,但如果您通过发出错误消息来处理这种情况,就可以避免一些混乱。

在我更正了其中的前两个之后,您的程序成功地为我运行了一个 "ls" 命令。