什么时候argv [0]有空?

时间:2010-05-08 13:03:06

标签: c argv

我从命令行向main()传递参数的原因是argc的最小值为1,而argv [0]的程序名称始终为其中的路径。

如果在命令行提供了参数,那么argc的值将大于1,而argv [argc-1]的argv 1将具有这些参数。

现在this link的段落说明了

  

argv [0]将是一个字符串,其中包含程序名称或空字符串(如果该字符串不可用)。

现在,argv [0]如何以及何时可以使用空字符串?我的意思是程序名称及其路径将始终可用,所以什么时候它可以为空?

作家说“如果那不可用”但是何时以及如何可能无法获得该计划名称?

4 个答案:

答案 0 :(得分:27)

使用exec类调用,您可以单独指定程序 name 和编程可执行文件,这样就可以将其设置为NULL。

但该引用实际上来自ISO标准(可能是转述),该标准涵盖了从最小的微控制器到最新的z10企业级大型机的极大范围的执行环境。

许多嵌入式系统都处于可执行名称毫无意义的情况。

来自最新的c1x草案:

  

argc的值应为非负值。

     

argv[argc]应为空指针。

     

如果argc的值大于零,则数组成员argv[0]argv[argc-1]包含指向字符串的指针,这些指针由主机环境事先给出实现定义的值程序启动。

这意味着,如果argc为零(可能是),则argv [0]为NULL。

但是,即使argc 0,您也可能无法获得程序名称,因为该标准还指出:

  

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

因此,标准中没有要求提供程序名称。我见过程序使用多种选项来表示这个值:

  • 根本没有价值(假设安全性)。
  • 一个公然的谎言(例如sleep用于恶意代码)。
  • 实际的程序名称(例如sleep)。
  • 略微修改过的(例如登录shell的-ksh)。
  • 描述性名称(例如progname - a program for something)。

答案 1 :(得分:6)

根据this mailing list,如果argv[0]argc == 0可以为空。但是,当 argc可能为零时,他们不解释。在没有“正常”启动可执行文件的情况下(即通过命令行,argc等),我怀疑 popen将为零 - 而且,正如@paxdiablo所提到的,您可以使用exec family of functions手动设置argv,因此argc可能为零,具体取决于这些参数。

但是,在 Rationale 部分:

  

早期提案要求传递给argc的{​​{1}}的值为“一个或更多”。这是由ISO C标准草案中的相同要求驱动的。实际上,当没有向exec函数的调用者提供参数时,历史实现已经传递了零值。此要求已从ISO C标准中删除,随后也从IEEE Std 1003.1-2001的该卷中删除。措辞,特别是单词should的使用,要求严格一致的POSIX应用程序将至少一个参数传递给exec函数,从而保证main()在被这样的应用程序调用时为1或更大。实际上,这是一种很好的做法,因为许多现有应用程序在未先检查argc的值的情况下引用argv[0]

所以你有它:严格遵守POSIX应用程序必须argc大于零,但这绝不是保证。

有关Program Startup部分中argcargc的标准的更多信息。

答案 2 :(得分:2)

可以想象程序没有名称的平台 - 也许代码只是在启动时加载。在那些,argv [0]我可以猜测是NULL。 C标准当然允许argc值为零,并且表示argv [argc]应为NULL。

答案 3 :(得分:1)

可运行的POSIX示例

<强> a.c

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *argv[] = {NULL};
    char *envp[] = {NULL};
    execve("b.out", argv, envp);
}

<强> b.c

#include <stdio.h>

int main(int argc, char **argv) {
    if (argc == 0 && argv[0] == NULL)
        puts("yup");
}

然后:

gcc a.c -o a.out
gcc b.c -o b.out
./a.out

给出:

yup

在Ubuntu 16.10中测试过。

使用空参数列表测试现有程序

这是一个以路径为参数的包装器,并将其作为没有args的命令运行:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char**argv) {
    char *empty[] = {NULL};
    execve(argv[1], empty, empty);
    perror("empty-args: execve failed");  // Bad Address (EFAULT) if our argv[1] == NULL
    return 1;
}

用法:

./empty-args ./arg-count