C argv数据的最大大小是多少

Jos*_*itt 8 c argv

可能重复:
关于main函数的命令行参数

我如何确定可以传递到C main的最大数据大小(int argc,char*argv)?标准中是否有一个宏来定义它?数据是否由主进程"拥有"(即我的程序是否存储此数据),还是由操作系统以某种方式"拥有",我可以获得指向它的指针?

Jon*_*ler 7

在POSIX系统中,有一个值,其中ARG_MAX定义<limits.h> 了最小可接受值_POSIX_ARG_MAX(即4096).您可以通过sysconf()SC_ARG_MAX参数的函数在运行时发现该值.

它通常是256 KiB.

中的数据argv(指针的两个阵列和它们指向的字符串)被程序"拥有".它们可以修改; 这是否合理取决于你的观点.如果main()不调用未定义的行为,你当然不能超出传递给函数的范围.GNU等getopt()函数在没有在环境中设置POSIXLY_CORRECT环境变量的情况下运行时重新组织参数.你已经有一个指针,指向的数据argv作为提供给main().

根据经验,您经常会发现字符串结尾后的数据argv[argc-1]实际上是环境的开始.主程序可以像int main(int argc, char **argv, char **envp)某些系统一样编写(在C标准附件J,§J.5.1中被认为是扩展),其中envp的值与存储在全局变量中的值相同environ,并且是空终止的开始指向环境字符串的指针数组.


can*_*cas 5

ARG_MAX 是新进程的最大参数长度

如果您尝试调用具有太多参数的程序,您将看到此错误消息,即最有可能与模式匹配相关:

$ command * 
Run Code Online (Sandbox Code Playgroud)

它只是exec()系统调用及其直接变体,这将产生此错误.它们返回相应的错误条件E2BIG().

shell不应该受到责备,它只是向您提供此错误.实际上,shell扩展不是问题,因为这里不需要exec().扩展仅受虚拟内存系统资源的限制.

因此,以下命令可以顺利运行,因为它们不是将过多的参数移交给新进程,而是仅使用shell内置(echo)或使用控制结构(for循环)遍历参数:

/dir-with-many-files$ echo * | wc -c
/dir-with-many-files$ for i in * ; do grep ARG_MAX "$i"; done
Run Code Online (Sandbox Code Playgroud)

有不同的方法来学习上限

命令: getconf ARG_MAX

系统调用: sysconf(_SC_ARG_MAX)

系统头:例如<[sys /] limits.h>中的ARG_MAX

与标题相反,sysconfgetconf告诉实际有效的限制.这与允许在运行时,通过重新配置,通过重新编译(例如Linux)或应用补丁(HP-UX 10)来更改它的系统相关.

示例用法sysconf():

#include <stdio.h>
#include <unistd.h>
int main() {
    return printf("ARG_MAX: %ld\n", sysconf(_SC_ARG_MAX));
}
Run Code Online (Sandbox Code Playgroud)

如果安装了cpp,则可以方便地在标头中找到限制:

cpp <<EOF
#include <limits.h>
#include <param.h>
#include <params.h>
#include <sys/limits.h>
#include <sys/param.h>
#include <sys/params.h>
arg_max: ARG_MAX
ncargs: NCARGS
EOF
Run Code Online (Sandbox Code Playgroud)

在查看ARG_MAX/时NCARGS,您必须考虑两者的空间消耗argv[]envp[](参数和环境).因此,你必须至少通过的结果,以减少ARG_MAX env|wc -cenv|wc -l * 4对当前可用空间的良好估计.

POSIX建议另外减去2048,以便该过程可以节省地修改其环境.使用getconf命令快速估算:

 expr `getconf ARG_MAX` - `env|wc -c` - `env|wc -l` \* 4 - 2048
Run Code Online (Sandbox Code Playgroud)

获得当前可用空间的最可靠方法是测试exec()的成功与增加的参数长度,直到失败.这可能很昂贵,但至少你需要检查一次,自动考虑envp []的长度,结果是可靠的.

或者,可以使用GNU autoconf检查 "检查命令行参数的最大长度......".它非常相似.

但是,由于意图和简单原因,它会产生更低的值(它可能只是实际值的四分之一):

在增加n的循环中,检查尝试使用参数长度为2n的exec()(但不会检查n高于16,即512kB).如果ARG_MAX是2的幂,则最大值为ARG_MAX/2.最后,找到的值除以2(为安全起见),原因是"C++编译器可以处理大量额外的参数".

实际价值

在Linux 2.6.23上,它是堆栈大小的1/4.内核代码供参考.