argc会溢出吗?


75

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

标准说argv[argc]必须是一个空指针,但是如果argc溢出,它将为假。

(我了一个小的C程序和一个python脚本对其进行测试,但得到了一个MemoryError。)

谢谢!


国际标准的理由-编程语言-C§5.1.2.2.1程序启动

的规范argcargv作为main广泛认可的先验实践的论据。argv[argc]也是根据惯例,必须为空指针,以提供对列表末尾的冗余检查。


13
Standard says that argv[argc] must be a null pointer but this will be false if argc overflow -我读成“不要让argc溢出”。(“医生,当我这样做时会很痛”)
罗伯特·哈维

4
在POSIX和大多数Linux系统上,mainexecve-安装的-的初始堆栈(包括其参数(即argv))要受限制得多(通常为几兆字节)。所以argc不到几个milions,我从来没有听说过的OS的地方argc可能是近INT_MAX
巴西莱Starynkevitch

6
可以说,在这种情况下,实现将具有系统特定的限制,从而无法将2 ^ 15的参数传递给程序
Nos

14
好吧,我当然不会在其中输入:)
马丁·詹姆斯

3
稍等一下,我的意思是“我不会感到惊讶”。任何LP64或LLP64架构都符合要求,因此Windows或Linux。但是,您将需要大量RAM。我想如果从头开始,argc应该有type size_t
史蒂夫·杰索普

Answers:


78

根据标准

因此,从您的报价:

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真的很大呢?

好的,假设您使用的是旧/古怪的系统,那么int16位也是如此,并且ARG_MAX远远超过2 15,这在其他方面还是很合理的。现在,假设您execve()使用2以上的15个参数进行调用。该实现有两个选择。

  1. 它可能会导致argc溢出...基本上是,丢弃数据,确保正在运行的程序以某种意外且可能错误的方式执行,并且违反了C标准。最糟糕的是,该错误是无声的,因此您可能永远都不知道。

  2. 或者,它可以简单地EOVERFLOW从返回execve(),通知您它根本无法运行具有这么多参数的映像。现在,POSIX / SUS标准没有提及任何有关此错误结果的信息……但是,我怀疑这仅仅是因为标准编写者从未期望ARG_MAX过大于INT_MAX

选项#2是唯一合理的选项。如果您的系统以某种方式选择了选项#1,则该选项已损坏,您应该提交错误报告。

另外,您可能试图运行为16位系统编译的旧程序,但正在通过某种仿真器或兼容性层运行它。如果您尝试将2 15个以上的参数传递给程序,我希望模拟器或兼容性层会给出错误消息。


但是,想象一下,您所处的系统中ARG_MAX值非常大(无论出于何种原因)并且可能发生。那会是什么样的失败?由于它仍然遵守该标准,因此可以称为C兼容,但是也可能发生未定义的行为,程序员没有选择要阻止的行为。这是什么错误?
dhein 2015年

我认为该标准具有未定义的行为,因为未定义签名溢出。
塞巴斯蒂安·马赫2015年

1
@zaibis要求为argv[argc]空指针意味着需要设置ARG_MAX足够小的值而argc 不会溢出。
zwol


10

我尝试了这个:

test.c:

然后用了一个大的zipfile

然后将文件作为测试程序的参数读取:

结果:

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

和:


2
当您只需$(seq 1 100000)时,为什么要使用zip文件生成参数?
pflaquerre

没想到。谢谢!
ehwas,2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.