【问题标题】:Double pointer as argument to execvp()双指针作为 execvp() 的参数
【发布时间】:2019-06-07 05:35:32
【问题描述】:

我正在尝试使用自定义**tokens 双指针作为输入来执行execvp(),而不是在“创建自定义外壳”分配中使用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

【问题讨论】:

  • char **tokens = malloc(sizeof(char)*512); 大小参数不正确。 tokens[i]=token; 令牌数组应以空指针终止。
  • 我尝试将这一行放在while 循环之后:`tokens[i] = NULL;` 仍然不起作用
  • 提供的代码从未将值分配给child_pid。如果那是一个局部变量,那么在您测试它时它的值是不确定的。在检查 pid 之前,您的意思是 child_pid = fork(); 吗?
  • 这里不需要WUNTRACED 选项。第三个参数使用 0。

标签: c shell execvp double-pointer


【解决方案1】:

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

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

  2. 如果缓冲区足够大以容纳它,则通过fgets 获得的字符串将包括直到并包括行的换行符的所有字符。您没有在标记分隔符中包含换行符,因此对于单字命令 ls,传递给 execvp() 的命令等效于 "ls\n"not "ls"ls\n 不太可能(但并非不可能)是您机器上的可用命令。

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

在我纠正了前两个之后,你的程序成功地为我运行了一个“ls”命令。

【讨论】:

    【解决方案2】:

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

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

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


    还要考虑@n.m指向的第一条评论

    【讨论】:

    • 在此编辑之后,它仍不会打印到我的终端
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    相关资源
    最近更新 更多