我在某处徘徊,看到了this question个.然后我开始怀疑我是否可以溢出argc.

标准要求argv[argc]必须是空指针,但如果argc溢出,这将是错误的.

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

谢谢!


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

argcargv指定为main的参数认可了广泛的先前实践.argv[argc]必须是空指针,以便为列表末尾提供冗余判断,这也是基于常见做法.

推荐答案

根据标准

所以,从你的话:

argv[argc]必须是空指针

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

实际上

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

在我的Linux/x64系统上:

$ getconf ARG_MAX
2097152

因此,总参数大小约为2兆字节,argc不能溢出.我相信这个限制衡量的是argv中的总数据和环境的组合.如果在try 运行命令时超过此限制,exec()将失败,E2BIG将失败.从man 2 execve开始:

E2BIG  The total number of bytes in the environment (envp) and argument
       list (argv) is too large.

我相信,与其他系统相比,我的系统的~2 MB限制相对宽松.我的OS X系统报告限制为约260KB.

But what if ARG_MAX were really big?

好的,让我们假设您在一个旧的/奇怪的系统上,所以int是16位,而arg_max远远大于215,否则这是相当合理的.现在,假设您使用2个以上的15参数调用execve().该实现有两个选项.

  1. 它可以让argc个溢出...基本上,扔掉你的数据,确保你正在运行的程序以某种意想不到的、可能是错误的方式执行,并且违反了C标准.最糟糕的是,错误是silent的,所以你可能永远不会知道.

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

选项2是only个合理选项.如果你的系统以某种方式 Select 了选项#1,那么它是broken,你应该提交一份错误报告.

或者,您可以try 运行一个为16位系统编译的旧程序,但您正在通过某种仿真器或兼容层来运行它.如果您试图向程序传递超过2个15参数,我希望emulator或兼容层会给出错误消息.

C++相关问答推荐

在C++中头文件中声明外部 struct

我可以在C中声明不同长度数组的数组而不带变量名吗?

使用C时,Windows CMD中的argc参数是否包含重定向命令?

限制不同类型的限定符

在C++中父进程和子进程中的TAILQ队列同步问题

GCC错误,共享内存未定义引用?

运行时错误:在索引数组时加载类型为';char';`的空指针

为什么编译器不能简单地将数据从EDI转移到EAX?

C";中的ANN运行时判断失败#2-变量outputLayer;周围的堆栈已损坏.运行后出错

基于蝶数恰好有8个除数的事实的代码

是否有单独的缓冲区用于读写库调用?

浮动目标文件,数据段

Dlsym()的手册页解决方法仍然容易出错?

从文件到链表读取日期

函数指针作为函数参数 - 应该使用 const 吗?

如何使用 VLA 语法使用 const 指针声明函数

UEFI 应用程序中的计时器回调仅在 AMI BIOS 中挂起

如何在 C 中的 Postgres 函数的表中 for 循环

为什么这里的符号没有解析?

从 COBOL 调用外部 C 库