电弧会溢出吗?

我在 SO 中徘徊,看到了 这个问题,然后我开始考虑是否可以溢出 argc。

标准规定 argv[argc]必须是空指针,但是如果 argc 溢出,则为 false。

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

谢谢!


国际标准ーー程序设计语言ーー C 5.1.2.2.1 < em > 程序启动

argcargv的规范作为 main的参数承认了广泛的先前实践。argv[argc]需要一个空指针来为列表的末尾提供一个冗余检查,也是基于通常的做法。

5364 次浏览

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

根据标准

所以,根据你的原话:

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.

我相信,与其他系统相比,我的系统大约2MB 的限制是相对宽松的。我的 OS X 系统报告一个 ~ 260KB 的限制。

但如果 ARG_MAX真的很大呢?

好的,让我们假设您使用的是一个古老/怪异的系统,所以 int是16位,而 ARG _ MAX 远远大于215,这在其他方面是相当合理的。现在,假设使用多于215参数调用 execve()。实现有两个选项。

  1. 它可以允许 argc溢出... ... 基本上,抛弃您的数据,确保您正在运行的程序以某种意想不到的、可能是错误的方式执行,并且违反 C 标准。最糟糕的是,错误是无声的,所以您可能永远不会知道。

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

选项 # 2是 只有合理的选项。如果您的系统以某种方式选择了选项 # 1,那么它就是 支离破碎,您应该提交错误报告。

或者,你可以尝试运行一个为16位系统编译的旧程序,但是你要通过某种模拟器或兼容层来运行它。如果你试图向一个程序传递超过2abc0的参数,我认为模拟器或兼容层会给出一个错误消息。

我试过了:

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

然后用了个大拉链

 ⚡⚡⚡  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 ]必须是一个有效的值。

因此,如果运行时环境不能保证这一点,那么它就不应该启动程序。