12

我最近看到了一些奇怪的东西。在 HHVM 源代码中,main()函数的前 3 行如下所示:

if (!argc) {
  return 0;
}

这有点傻,但我还是忍不住想知道……为什么要返回 0!?并不是我认为有一些正确的方法来处理这个问题,而是返回 0,通常与成功相关,似乎特别不合适。

除了不崩溃之外,是否存在0有适当响应的argc情况?(或者甚至小于 0?)这有关系吗?

我所知道的以argc0 结尾的唯一方法是exec()和朋友一起。如果由于某种原因确实发生了这种情况,那几乎可以肯定是调用者中的一个错误,而被调用者对此无能为力。

(标记为 C 和 C++,因为我希望这两种语言的答案是相同的)

编辑:为了尝试使问题不那么模糊和哲学,我将提供一个替代方案。

if (!argc) {
  puts("Error: argc == 0");
  return 1;
}

关键点是有错误指示并返回非零值。极不可能需要这样做,但如果是这样,您不妨尝试指出错误。另一方面,如果检测到的错误严重到argc等于 0,那么尝试访问 stdout 或 C 标准库可能是有原因的。

4

2 回答 2

8

请注意,C11 标准明确允许argc == 0

5.1.2.2.1 程序启动

¶1 程序启动时调用的函数名为main. 实现没有声明这个函数的原型。它应定义为返回类型int且不带参数:

int main(void) { /* ... */ }

或带有两个参数(这里称为argcand argv,尽管可以使用任何名称,因为它们对于声明它们的函数是本地的):

int main(int argc, char *argv[]) { /* ... */ }

或同等学历; 10)或以其他一些实现定义的方式。

¶2如果它们被声明,main函数的参数应遵守以下约束:

  • argc 的值应为非负数。
  • argv[argc]应为空指针。
  • 如果 的值argc大于零,则argv[0]通过 argv[argc-1]inclusive 的数组成员应包含指向字符串的指针,这些指针在程序启动之前由宿主环境赋予实现定义的值。目的是从托管环境中的其他地方向程序提供在程序启动之前确定的信息。如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串。
  • 如果 的值argc大于零,则 指向的字符串argv[0] 代表程序名argv[0][0]如果主机环境中没有程序名,则应为空字符。如果 的值argc大于 1,则argv[1]through指向的字符串argv[argc-1] 表示程序参数
  • 数组所指向的参数argc和字符串应可由程序修改,并在程序启动和程序终止之间保留其最后存储的值。argvargv

10)因此,int可以替换为定义为 的 typedef 名称int,或者argv可以写为 的类型char ** argv,依此类推。

两个要点说“如果 的值argc大于零”显然允许argc == 0,尽管这种情况是不寻常的。

因此,理论上,程序可以对其采取预防措施,argv[0] == 0即使argc == 0, 只要代码不取消引用空指针,它应该没问题。许多程序,甚至大多数程序,都没有采取这种预防措施;他们假设这argv[0]不会是一个空指针。

于 2015-01-19T07:32:52.420 回答
4

由于HHVM的源代码(文件hphp/hhvm/main.cpp)中的以下片段,我认为这只是防御性编程的一个案例:

int main(int argc, char** argv) {
  if (!argc) {
    return 0;
  }
  HPHP::checkBuild();
  int len = strlen(argv[0]);

在行中:

int len = strlen(argv[0]);

if argc == 0-> argv[0] == NULLandstrlen(argv[0])会导致分段错误。

我不熟悉HHVM,但他们可以假设某些程序可以在没有参数的情况下调用该程序(甚至不是程序名称)。

于 2015-01-19T00:03:11.050 回答