我正试图用一个用命令行参数构建的路径名运行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
,则可以使用snprintf
和malloc
自己滚动它。如果你没有一台真正的电脑。)关于c - c unix execl无法与使用strcat构建的字符串一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27322318/