【发布时间】:2017-10-23 19:23:03
【问题描述】:
我已经阅读了几页(如this one)关于如何在 Linux 上正确解释 ARG_MAX。据我所知,每个参数/环境变量占用一个指针的大小,再加上它的长度为 nul 终止的字符串本身。填充物可能还占用了一些额外的空间。然而,即使在给自己 2K 的额外空间之后,我在尝试 exec() 长命令行时仍然遇到 E2BIG。这是什么原因造成的?
我认为它可能是auxiliary vector,但即使添加它的大小(在我的情况下为 320 字节)也无济于事。我也远低于MAX_ARG_STRINGS 和MAX_ARG_STRLEN(见https://unix.stackexchange.com/a/120842/56202)。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern char **environ;
size_t arg_size(const char *arg) {
// Count the string as well as the argv/environ pointer to it
size_t size = sizeof(arg);
if (arg) {
size += strlen(arg) + 1;
}
return size;
}
int main() {
size_t arg_max = sysconf(_SC_ARG_MAX);
arg_max -= 2048; // POSIX recommends 2048 bytes of additional headroom
printf("arg_max: %zu\n", arg_max);
size_t size = 320; // For the auxiliary vector
for (char **envp = environ; *envp; ++envp) {
size += arg_size(*envp);
}
size += arg_size(NULL);
char *argv[100001] = {"true"};
size += arg_size(argv[0]);
size += arg_size(NULL);
char *arg = "0123456789ABCDEF0123456789ABCDEF"
"0123456789ABCDEF0123456789ABCDEF";
size_t each_size = arg_size(arg);
size_t i;
for (i = 1; i < 100000 && size + each_size < arg_max; ++i) {
argv[i] = arg;
size += each_size;
}
argv[i] = NULL;
printf("size: %zu, argc: %zu\n", size, i);
assert(size < arg_max);
execvp(argv[0], argv);
perror("execvp()");
return EXIT_FAILURE;
}
$ gcc e2big.c -o e2big && ./e2big arg_max: 2095104 size: 2095059, argc: 28640 execvp(): Argument list too long
为了完整起见,这是开启
$ uname -a Linux superluminal 4.13.7-1-ARCH #1 SMP PREEMPT Sat Oct 14 20:13:26 CEST 2017 x86_64 GNU/Linux
【问题讨论】:
-
这就是说,计算指针的大小是没有意义的。
-
@Jean-FrançoisFabre 确实如此,
argv数组本身就像它指向的数据一样占用空间。 -
我认为他的意思可能是
sizeof(arg)是指针的大小,而不是它指向的数据的大小。 -
@WeatherVane ...但我两个都算?
-
@WeatherVane 不,我看到了。 OP 正在计算指针的大小 + 字符串的大小 + 1