在任何C程序中,命令行参数argv[0]
指向用于调用程序的名称。是否有任何情况会指向空字符串""
?
这种情况的示例代码段将是一个很好的参考。
答案 0 :(得分:9)
它是实现定义的。 §5.1.2.2.1删节:
如果
argc
的值大于零,则数组成员argv[0]
通过argv[argc-1]
包含应包含指向字符串的指针 程序启动前主机环境实现定义的值。该 意图是在程序启动之前为程序提供信息 来自托管环境中的其他地方。 [...]如果
argc
的值大于零,则argv[0]
指向的字符串 代表程序名称;argv[0][0]
如果是,则为空字符 程序名称不能从主机环境中获得。 [...]
因此,如果argc
大于零,那么意图 argv[0]
永远不会是空字符串,但它可能会发生。 (请注意,当argc
等于n
时,argv[0]
到argv[n - 1]
永远不会为空且始终指向字符串。但字符串本身可能为空。如果{{{} 1}}为零,n
为空。)
在实践中,当然,您只需要确保目标平台的行为符合要求。
答案 1 :(得分:7)
是
C语言标准明确允许argv[0]
可以是空指针,或,它可以指向空字符串(""
)。 N1256 5.1.2.2.1p2:
argc 的值应为非负值。
argv [argc] 应为空指针。
[...]
如果 argc 的值大于零,则指向该字符串 通过 argv [0] 表示程序名称; argv [0] [0] 应该是 如果程序名称不可从主机获得,则为null字符 环境。如果 argc 的值大于1,则为字符串 argv [1] 指向 argv [argc-1] 代表 程序参数。
在类Unix系统上,程序由exec()
函数族之一(execl()
,execlp()
等)调用,这允许调用者准确指定哪些参数传递给main()
函数。 (甚至可以以违反C标准要求的方式调用程序。)
请注意,标准表示argv[0]
(假设它既不为空也不为空)“表示程序名称”。该标准故意模糊如何它代表程序名称。特别是,它不需要提供一个可以调用程序的名称(因为标准甚至不要求可以通过名称调用程序)。
答案 2 :(得分:5)
其他回复引用了C标准并显示argv[0]
并且可以是NULL
,或者它可以是空字符串(""
)。您应该在假设可能发生这种情况的情况下编写程序,否则您将产生(小)安全风险。调用程序并将argv
设置为攻击者想要的任何内容都很容易。作为证据,请考虑以下两个程序。第一个echoargv.c
打印出argv
的内容:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i;
for (i = 0; i < argc; ++i)
printf("argv[%d] = \"%s\"\n", i, argv[i]);
exit(0);
}
第二个,argv0
,调用任何其他程序,让用户指定其他程序的argv:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
(void) execv(argv[1], argv+2);
perror("execv");
exit(1);
}
(这是特定于Posix的版本。非标准环境可能需要更改。)
以下是如何使用它们:
$ gcc -o echoargv echoargv.c
$ gcc -o argv0 argv0.c
$ ./argv0 ./echoargv
$ ./argv0 ./echoargv ''
argv[0] = ""
$ ./argv0 ./echoargv 'this is fun' 'it is fun indeed'
argv[0] = "this is fun"
argv[1] = "it is fun indeed"
$
第一轮argv0
将echoargv
的{{1}}设置为NULL。
第二次运行使它成为空字符串。
第三次运行只是为了好玩:注意argv[0]
不需要如何
与程序的实际名称有关。
这怎么能咬你?例如,如果您在使用消息中盲目打印出程序名称:
argv[0]
更好:
printf("usage: %s [options] [FILE]...\n", argv[0]);
如果您不这样做,攻击者可能会导致您的程序出现段错误,或者可能让您的程序向用户报告完全错误的内容。
答案 3 :(得分:1)
argv [0]在C中可以为null,例如,如果直接调用main函数(可以在C中完成一些技巧)。我不知道C ++是否允许直接主调用。