Linux에서 ARG_MAX를 올바르게 계산하는 방법에 대한 몇 페이지 (예 : this one)를 읽었습니다. 내가 알 수있는 한, 각 인수/환경 변수는 포인터의 크기를 취하고, 하나는 null로 끝나는 문자열 자체의 길이를 더한 값입니다. 패딩으로 추가 공간을 차지할 가능성이 있습니다. 그러나 2K 여분의 헤드 룸을 제공 한 후에도 exec()
긴 명령 행을 시도 할 때 E2BIG를 실행 중입니다. 이 문제의 원인은 무엇입니까?인수와 환경을 고려할 때 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 = "ABCDEFABCDEF"
"ABCDEFABCDEF";
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;
}
완성도를 들어
,이 UB 세계에$ 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)가 가리키는 데이터의 크기가 아니라 포인터의 크기라는 것을 의미한다고 생각합니다. –