execvp的地址错误

时间:2017-03-01 20:04:03

标签: c shell unix operating-system execvp

我试图制作一个贝壳"波什>"它接收Unix命令并不断收到错误的地址错误。我知道我的代码读入命令并解析它们但由于某种原因,我无法让它们执行,相反,我得到了一个错误的地址"错误。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_LINE 128
#define MAX_ARGS 10



int main(){
    pid_t pid;
    char command[MAX_LINE]; /*command line buffer*/
    char *commandArgs[MAX_ARGS]; /*command line arg*/
    int i;
    char *sPtr=strtok(command," ");
    int n=0;


    printf("bosh>");
    fgets(command, MAX_LINE-1,stdin);
    command[strlen(command)-1]='\0';


    while(strcmp(command,"quit")!=0)
    {
        n=0;

        sPtr=strtok(command," ");
        while(sPtr&&n<MAX_ARGS)
        {
            sPtr=strtok(NULL," ");
            n++;
        }

        commandArgs[0]=malloc(strlen(command)+1);
        strcpy(commandArgs[0],command);

        if(fork()==0)
        {
            execvp(commandArgs[0],commandArgs);
            perror("execvp failed");
            exit(2);
        }
        pid=wait(NULL);


        printf("%s",">" );
        fgets(command, MAX_LINE-1,stdin);
        command[strlen(command)-1]='\0';
    }

    printf("Command (%d) done\n", pid);

    return 0;


}

2 个答案:

答案 0 :(得分:3)

这两行是罪魁祸首:

commandArgs[0]=malloc(strlen(command)+1);
strcpy(commandArgs[0],command);

首先,malloc(strlen(...))后跟strcpy是POSIX函数strdup已经执行的操作。但是,你甚至不需要复制字符串 - 只需将指向原始字符串的指针存储到commandArgs[0]中即可:

commandArgs[0] = command;

但是,execvp该命令将采用多少个参数?如果您仔细阅读手册,他们会说:

  

execv()execvp()execvpe()函数提供了一个指向以null结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。 指针数组必须以空指针终止。

您的参数数组不以NULL结尾。要修复它,请使用

commandArgs[0] = command;
commandArgs[1] = NULL; // !!!!

(然后您注意到您实际上想要在 strtok解析循环中分配参数,以便您可以实际分配所有参数进入commandArgs数组;并在启用所有警告的情况下编译并解决这些问题,等等。)

答案 1 :(得分:1)

您在其声明中初始化sPtr,您不需要这样做,因为您从不使用初始值。但初始化会产生未定义的行为,因为它取决于command数组的内容,此时该数组是不确定的。

作为execvp()的第二个参数传递的数组应该在最后一个参数后包含一个NULL指针。你不能确保你的确如此。

您还可能因为未能将令牌分配给commandArgs[]而将所有参数都删除到输入命令。标记化后,您复制第一个标记(仅限)并将副本分配给commandArgs的第一个元素,但忽略任何其他标记。