argc 会溢出吗?

Can argc overflow?

我在SO里闲逛,看到了this question。然后就开始想能不能溢出argc。

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

(我 wrote 一个小的 C 程序和一个 python 脚本来测试它但是得到了一个 MemoryError。)

谢谢!


Rationale for International Standard — Programming Languages — C §5.1.2.2.1 Program startup

The specification of argc and argv as arguments to main recognizes extensive prior practice. argv[argc] is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.

在实践中,不,你不能。大多数系统对 argvenvp 的总组合大小设置了相对较低的限制。几十到几百 KB 的限制并不少见。有关各种操作系统限制的相当全面的列表,请参阅 http://www.in-ulm.de/~mascheck/various/argmax/

按照标准

因此,根据您的引述:

argv[argc] is required to be a null pointer

因此,argc不能溢出,因为那样上面的说法就不成立了。

在实践中

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

在我的 Linux/x64 系统上:

$ getconf ARG_MAX
2097152

因此,总参数大小约为2MB,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 真的很大呢?

好吧,假设你在 old/weird 系统上,所以 int 是 16 位,而 ARG_MAX 远远超过 215,这在其他方面是相当合理的。现在,假设您使用超过 215 个参数调用 execve()。实现有两个选项。

  1. 它可以让 argc 溢出...基本上,扔掉你的数据,确保你正在 运行ning 的程序在一些意外的和可能错误的情况下执行方式,并且违反了 C 标准。最糟糕的是,错误是无声的,因此您可能永远不会知道。

  2. 或者,它可以简单地从 execve() return EOVERFLOW,告诉你它根本无法 运行 一个图像有那么多参数。现在,POSIX / SUS 标准没有提及任何关于这个错误结果的信息......但是,我怀疑这仅仅是因为标准编写者从未预料到 ARG_MAX 会大于 INT_MAX.

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

或者,您可以尝试 运行 为 16 位系统编译的旧程序,但您 运行 通过某种仿真器或兼容层对其进行编译。如果您尝试将超过 215 个参数传递给程序,我希望仿真器或兼容层会给出错误消息。

我试过这个:

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;
}

然后用了一个大zip文件

 ⚡⚡⚡  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

根据标准,argv[argc] 必须是有效值。

所以如果运行-时间环境处于无法保证的情况下,则不应启动程序。