【问题标题】:Having trouble with execvpexecvp 遇到问题
【发布时间】:2019-07-26 10:52:32
【问题描述】:

我在尝试用 c 编写的基本 shell 程序时遇到了一些问题。每当我尝试在诸如 ls 之类的函数中调用 exec 时,execvp 都会返回一个错误,指出找不到文件或目录。我认为问题在于解析,因为在 main 中,可以打印命令,但在函数中它是空白的。谢谢

这是函数的代码:

int extern_process(char *arg[]){
    pid_t pid;
    int errnum, ifFail;
    printf("i%si\n",arg[0]);
    pid = fork();

    if(pid == -1){
        errnum = errno;
        fprintf(stderr,"Error: fork %s", strerror(errnum));
        return FAIL;
    } else if(pid == 0){
        ifFail = execvp(arg[0],arg);
        if(ifFail < 0){
            errnum = errno;
            fprintf(stderr,"Error: exec %s", strerror(errnum));
            return FAIL;
        }
    } else {
        pid = wait(NULL);
    }
    return SUCCESS;
}

下面是解析函数的代码,以防万一:

void parse_cmd(char *retval[], char *cmd){
    char *tmp;
    char a[100];
    strcpy(a,cmd);
    int i = 0;
    tmp = strtok(a," \n\t\0");

    if(retval == NULL){
        fprintf(stderr, "Error with allocation\n");
        return;
    }
    if(tmp == NULL){
        printf("Error with parsing.\n");
        return;
    }
    while(tmp != NULL){
        retval[i] = tmp;
        tmp = strtok(NULL," \n\t\0");
        i++;
    }
    retval[i] = NULL;
}

这是输出:

shell> ls 
ls
i i 
Error: exec no file or directory found 

【问题讨论】:

  • 但根据您的代码,i i 表示您尝试执行的命令为空。因此,您对extern_process 的论点看起来是错误的。您需要提供调用该函数的代码。
  • 不会完全为空,可能是空格" "" \n\t\0" 也是多余的,应该只是 " \n\t"(字符串常量已经以 '\0' 结尾)。
  • 当 this:parse_cmd() 返回时,char *retval[] 将包含指向本地数组的指针:a[100] 但是,当函数退出时,该数组将“超出范围”,因此访问它是未定义的行为
  • 关于:ifFail = execvp(arg[0],arg); 这是不正确的,建议:execvp(arg[0],arg); perror( "execvp failed" )' exit( EXIT_FAILURE ); 不要return;,因为子进程将被执行并且您不希望子进程返回给功能:extern_process()

标签: c shell execvp


【解决方案1】:

我很确定 strtok 返回一个指向第一个参数的指针,在您的情况下,它是一个堆栈分配。我相信,返回指向该堆栈分配的指针数组会导致未定义的行为。这可能是也可能不是您的问题的原因。不看更多代码很难知道。要进行测试,请尝试像这样更改这部分代码:

void parse_cmd(char *retval[], char *cmd){
    char *tmp;
    char *a = strdup(cmd);
    int i = 0;

在生产中使用它之前,您需要想出一些方法来确保释放“a”,否则就会泄漏。也许您可以直接返回它而不是 void 并从其他地方释放它,或者您实际上可以 strdup() 每个标记并编写一个函数来释放它们全部或任何适合您的方法。

如果还有其他问题,可能在其他代码中。我真的没有看到这里有什么问题。

【讨论】:

  • 谢谢,我试过了,它似乎解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 2021-08-09
  • 2017-05-02
  • 2021-02-01
  • 2012-10-31
  • 2018-01-07
相关资源
最近更新 更多