argc能溢出吗?

我在这里徘徊,看到了这个问题 。 然后我开始怀疑是否可以溢出argc。

标准说argv[argc]必须是一个空指针,但是如果argc溢出,这将是错误的。

(我写了一个小C程序和一个python脚本来testing它,但得到了一个MemoryError 。)

谢谢!


国际标准的基本原理 – 编程语言 – C§5.1.2.2.1 程序启动

argcargv作为main参数的规范认可了大量的先前的实践。 argv[argc]必须是一个空指针,以便在列表的末尾提供冗余检查,同样也是基于惯例。

根据标准

所以,从你的报价:

argv[argc]必须是空指针

所以argc不能溢出,因为那么上面的说法就不对了。

在实践中

实际上,传递给程序的参数总大小是有限的。

在我的Linux / x64系统上:

 $ getconf ARG_MAX
 2097152

因此,总参数大小约为2兆字节, argc不能溢出。 我相信这个限制是衡量argv和环境总数据的组合。 如果在尝试运行命令时超出此限制, exec()将以E2BIG失败。 从man 2 execve

 E2BIG环境(envp)和参数中的总字节数
       列表(argv)太大。

我相信我的系统上的〜2兆字节的限制与其他系统相比是相当大的。 我的OS X系统报告约260KB的限制。

但是,如果ARG_MAX真的很大?

好吧,假设你是一个古怪的系统,所以int是16位,而ARG_MAX远远超过了2-15 ,否则这是非常合理的。 现在,假设你用多于2 15个参数来调用execve() 。 实施有两个select。

  1. 它可以允许argc溢出…基本上,扔掉你的数据,确保你正在运行的程序执行一些意想不到的,可能是错误的方式,违反了C标准。 最糟糕的是,错误是沉默的,所以你可能永远不知道。

  2. 或者,它可以简单地从execve()返回EOVERFLOW ,通知你它不能运行那么多参数的图像。 现在,POSIX / SUS标准没有提到这个错误结果的任何内容……但是,我怀疑这只是因为标准编写者从未期望ARG_MAX大于INT_MAX

选项#2是唯一合理的选项。 如果你的系统以某种方式select选项#1,那么它被打破 ,你应该提交一个错误报告。

或者,您可能试图运行一个为16位系统编译的旧程序,但是您正在通过某种模拟器或兼容层运行它。 如果您试图将超过2 15个parameter passing给程序,我期望仿真器或兼容性层会给出错误消息。

在实践中,不,你不能。 大多数系统对argvenvp组合大小的限制相对较低。 几十到几百KB的限制并不less见; 请参阅http://www.in-ulm.de/~mascheck/various/argmax/了解各种操作系统的限制。;

我试过这个:

test.c:

  ⚡⚡⚡ more test.c #include <stdio.h> int main(int argc, char **argv) { printf("argc = %d\n", argc); printf("Size of argc = %d\n", sizeof(argc)); return 0; } 

然后使用一个大的zipfile

  ⚡⚡⚡ ls -h bigfile -rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile 

然后将该文件作为参数读取到testing程序中:

 ⚡⚡⚡ ./test $(more bigfile) 

结果:

 5 minutes nothing happend, then everything froze 

然后我尝试了一个较小的文件:

  ⚡⚡⚡ ls -h notsobigfile -rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile 

和:

  ⚡⚡⚡ ./test $(more notsobigfile) bash: ./test: Argument list too long 

如标准所示,argv [argc]必须是有效的值。

所以如果运行环境处于不能保证的情况下,就不应该启动程序。