我在SO中徘徊,看到了this question。然后我开始想知道我是否可以溢出argc。
标准表示argv[argc]
必须是空指针,但如果argc溢出则为false。
(我wrote一个小C程序和一个python脚本来测试它但得到了MemoryError
。)
谢谢!
Rationale for International Standard — Programming Languages — C§5.1.2.2.1程序启动
作为
argc
的参数的argv
和main
的规范认可了广泛的先前实践。argv[argc]
必须是一个空指针,以便在列表末尾提供冗余检查,同样基于通常的做法。
答案 0 :(得分:78)
所以,从你的引用:
argv[argc]
必须是空指针
因此,argc
不能溢出,因为上面的陈述不会是真的。
实际上,传递给程序的参数的总大小是有限的。
在我的Linux / x64系统上:
$ getconf ARG_MAX 2097152
因此,总参数大小约为2兆字节,argc
不能溢出。我认为此限制衡量的是argv
中的总数据与环境的组合。如果在尝试运行命令时超出此限制,exec()
将失败并显示E2BIG
。来自man 2 execve
:
E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.
我认为与其他系统相比,我系统的~2兆字节限制相对慷慨。我的OS X系统报告的限制为~260KB。
ARG_MAX
真的很大怎么办?好吧,我们假设您使用的是旧的/奇怪的系统,因此int
为16位,ARG_MAX远远超过2 15 ,否则非常合理。现在,假设您使用超过2个 15 参数调用execve()
。实施有两个选择。
它可以允许argc
溢出...基本上,丢弃您的数据,确保您正在运行的程序以某种意外的,可能是错误的方式执行,并违反C标准。最糟糕的是,错误是沉默的,所以你可能永远不会知道。
或者,它只能从EOVERFLOW
返回execve()
,告知您它无法运行包含那么多参数的图像。现在,POSIX / SUS标准没有提到有关此错误结果的任何内容......但是,我怀疑这只是因为标准编写者从未期望ARG_MAX
大于INT_MAX
。
选项#2是唯一的合理选项。如果您的系统以某种方式选择选项#1,那么已损坏并且您应该提交错误报告。
或者,您可能尝试运行为16位系统编译的旧程序,但是您通过某种仿真器或兼容层运行它。如果您尝试将超过2个 15 参数传递给程序,我希望仿真器或兼容性层会给出错误消息。
答案 1 :(得分:17)
在实践中,不,你不能。大多数系统对argv
和envp
的总组合大小设置相对较低的限制。数十至数百KB的限制并不罕见;请参阅http://www.in-ulm.de/~mascheck/various/argmax/,了解各种操作系统限制的相当全面的列表。
答案 2 :(得分:10)
我试过了:
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
然后将该文件作为测试程序的参数读取:
⚡⚡⚡ ./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
答案 3 :(得分:2)
如标准所示,argv [argc]必须是有效值。
因此,如果运行时环境处于无法保证的状态,则不应启动该程序。