我正试图用一个用命令行参数构建的路径名运行exec。它不起作用,所以我硬编码串接的字符串,所以它仍然不起作用。如果我提供一个char*path=“some path name”并将其传递给execl,那么它可以正常工作。

#include <stdio.h>

int main(int argc,char *argv[]){
//set char path name
 char pathname[256];
 strcat(pathname,"/bin/");
 strcat(pathname,"ls"); //"ls" will be replaced with arg[1]
 int pid=fork();
  if (pid==0){
     execl(pathname,"ls",(char *)0);
  }
  else{
  wait((int*)0);
  }
return 0;
}

我已经打印出路径名以确保它是“/bin/ls”。

最佳答案

问题在于:

char pathname[256];
strcat(pathname,"/bin/");

您没有初始化pathname。因此,它的内容是“不确定的”,对strcat的调用有一种官方称为未定义的行为——它可以做任何字面上的事情。可能发生的具体情况是,分配给pathname的内存空间中有一些二进制垃圾,并且strcat愉快地将其作为字符串处理,因此两个pathname调用之后的strcat内容类似于(十六进制)
01 02 03 2f 62 69 63 2f 6c 73 00

当您打印出字符串时,前面的控制字符不可见,但是当您调用execl时,内核欣然接受了执行名为"\001\002\003/bin/ls"的文件(当然是相对于当前工作目录)的请求,并且由于没有这样的文件,因此失败并将errno设置为ENOENT。紧跟在perror(pathname)之后的execl和用./a.out 2>&1 | cat -v调用的程序
^A^B^C/bin/ls: No such file or directory

将第一个strcat更改为strcpy可以更正此问题,因为strcpy总是复制到目标缓冲区的开头,而忽略之前存在的任何内容;完成此操作后,buf到第一个NUL(包括第一个NUL)的字节是确定的,strcat具有定义良好的行为。。。
... 但是,如果您将程序改回从/bin/读取argv[1]之后要复制的内容,并且第一个命令行参数的长度超过250字节,bang,则再次出现未定义的行为。编写此程序的更好方法是使用asprintf
int main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "usage: %s program\n", argv[0]);
        return 2;
    }
    char *pathname;
    if (asprintf(&pathname, "/bin/%s", argv[1]) == -1) {
        perror("asprintf");
        return 1;
    }

    execl(pathname, argv[1], (char *)0);
    perror(pathname);
    return 127;
}

(如果您没有asprintf,则可以使用snprintfmalloc自己滚动它。如果你没有一台真正的电脑。)

关于c - c unix execl无法与使用strcat构建的字符串一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27322318/

10-11 19:28