argc能溢出吗?
我在这里徘徊,看到了这个问题 。 然后我开始怀疑是否可以溢出argc。
标准说argv[argc]
必须是一个空指针,但是如果argc溢出,这将是错误的。
(我写了一个小C程序和一个python脚本来testing它,但得到了一个MemoryError
。)
谢谢!
国际标准的基本原理 – 编程语言 – C§5.1.2.2.1 程序启动
argc
和argv
作为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。
-
它可以允许
argc
溢出…基本上,扔掉你的数据,确保你正在运行的程序执行一些意想不到的,可能是错误的方式,违反了C标准。 最糟糕的是,错误是沉默的,所以你可能永远不知道。 -
或者,它可以简单地从
execve()
返回EOVERFLOW
,通知你它不能运行那么多参数的图像。 现在,POSIX / SUS标准没有提到这个错误结果的任何内容……但是,我怀疑这只是因为标准编写者从未期望ARG_MAX
大于INT_MAX
。
选项#2是唯一合理的选项。 如果你的系统以某种方式select选项#1,那么它被打破 ,你应该提交一个错误报告。
或者,您可能试图运行一个为16位系统编译的旧程序,但是您正在通过某种模拟器或兼容层运行它。 如果您试图将超过2 15个parameter passing给程序,我期望仿真器或兼容性层会给出错误消息。
在实践中,不,你不能。 大多数系统对argv
和envp
组合大小的限制相对较低。 几十到几百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]必须是有效的值。
所以如果运行环境处于不能保证的情况下,就不应该启动程序。