9

在任何 C 程序中,命令行参数argv[0]都指向用于调用程序的名称。在任何情况下它会指向一个空字符串""

这种情况的示例代码片段将是一个很好的参考。

4

4 回答 4

9

它是实现定义的。§5.1.2.2.1 节略:

  • 如果 的值argc大于零,则argv[0]通过 argv[argc-1]inclusive 的数组成员应包含指向字符串的指针,这些指针在程序启动之前由宿主环境赋予实现定义的值。目的是从托管环境中的其他地方向程序提供在程序启动之前确定的信息。[...]

  • 如果 的值argc大于零,则 指向的字符串argv[0] 代表程序名;argv[0][0]如果主机环境中没有程序名,则应为空字符。[...]

因此,如果argc大于零,则绝对不会argv[0]是空字符串,但它可能会发生。(请注意,对于argc等于nargv[0]通过argv[n - 1]永远不会为空,并且始终指向一个字符串。不过,字符串本身可能为空。如果n为零,argv[0]则为空。)

当然,在实践中,您只需要确保您的目标平台按需要运行即可。

于 2011-12-29T08:32:13.997 回答
7

是的。

C 语言标准明确允许argv[0]空指针指向空字符串 ( "") 的可能性。N1256 5.1.2.2.1p2:

argc的值应为非负数。

argv[argc]应该是一个空指针。

[...]

如果argc的值大于零,则argv[0]指向的字符串代表程序名如果程序名称在主机环境中不可用,则argv[0][0]应为空字符。如果argc的值大于 1,则argv[1]argv[argc-1]指向的字符串代表 程序参数

在类 Unix 系统上,程序由exec()函数族(execl()execlp()等)之一调用,它允许调用者准确指定传递给main()函数的参数。(甚至有可能以违反 C 标准要求的方式调用程序。)

请注意,标准说argv[0](假设它既不是 null 也不是空的)“代表程序名称”。该标准故意模糊它如何表示程序名称。特别是,它不需要提供可以调用程序的名称(因为标准甚至不要求程序可以通过名称调用)。

于 2011-12-29T08:33:12.113 回答
6

其他回复引用了 C 标准并表明argv[0]and 可以是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"
$ 

第一次运行的setsargv0为NULL。第二次运行使其成为空字符串。第三次运行只是为了好玩:注意不需要与程序的实际名称有任何关系。echoargvargv[0]argv[0]

这怎么能咬你?例如,如果您在使用消息中盲目地打印出程序的名称:

printf("usage: %s [options] [FILE]...\n", argv[0]);

更好的:

const char *program_name = "some default name"; /* (global) variable */
if (argv[0] && argv[0][0])
    program_name = argv[0];
printf("usage: %s [options] [FILE]...\n", program_name);

如果您不这样做,攻击者可能会导致您的程序随意发生段错误,或者可能让您的程序向用户报告完全错误的事情。

于 2011-12-29T09:11:23.200 回答
1

argv[0] 在 C 中可以为 null,例如,如果您直接调用 main 函数(可以在 C 中完成一些技巧)。我不知道 C++ 是否允许直接主调用。

于 2011-12-29T08:25:55.907 回答