C argv каков максимальный размер данных [дубликат]


Возможный дубликат:
о аргументах командной строки главной функции

Как бы я определил, какой максимальный размер данных я мог бы передать в C main (int argc, char* argv)? Есть ли где-нибудь в стандарте макрос, который бы это определял? Являются ли данные "собственностью" основного процесса (т. е. хранит ли моя программа эти данные) или они каким-то образом "принадлежат" операционной системе, и я могу просто получить на них указатель?

4 5

4 ответа:

В системе POSIX существует значение ARG_MAX, определенное в <limits.h> С минимально допустимым значением _POSIX_ARG_MAX (равным 4096). Вы можете узнать значение во время выполнения через sysconf() функция с параметром SC_ARG_MAX.

Это часто 256 Кб.

Данные в 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, и является началом массива нулевых указателей на строки окружения.

ARG_MAX - максимальная длина аргументов для нового процесса

Вы увидите это сообщение об ошибке, если вы попытались вызвать программу со слишком большим количеством аргументов, то есть, скорее всего, в связи с сопоставлением шаблонов:

$ command * 

Только системный вызов exec() и его прямые варианты приведут к этой ошибке. Они возвращают соответствующее условие ошибки E2BIG ().

Оболочка не виновата, она просто доставляет вам эту ошибку. На самом деле, расширение оболочки не является проблема, потому что здесь exec() пока не нужен. Расширение ограничено только ресурсами системы виртуальной памяти.

Таким образом, следующие команды работают гладко, потому что вместо того, чтобы передавать слишком много аргументов новому процессу, они только используют встроенную оболочку (echo) или повторяют аргументы с управляющей структурой (для цикла):
/dir-with-many-files$ echo * | wc -c
/dir-with-many-files$ for i in * ; do grep ARG_MAX "$i"; done

Существуют различные способы узнать верхний предел

Команда: getconf ARG_MAX

Система вызов: sysconf (_SC_ARG_MAX)

Системный заголовок: ARG_MAX, например, в пределах

В отличие от заголовков, sysconf и getconf сообщают предел, который фактически действует. Это актуально для систем, которые позволяют изменять его во время выполнения, путем реконфигурации, путем перекомпиляции (например, Linux) или путем применения патчей (HP-UX 10).

Пример использования sysconf():

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

Удобный способ найти ограничения в заголовках, если у вас есть 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

При взгляде на ARG_MAX/NCARGS, вы должны учитывать потребление пространства как argv[], так и envp[] (Аргументы и среда). Таким образом, вы должны уменьшить ARG_MAX по крайней мере на результаты env|wc -c и env|wc -l * 4 для хорошей оценки текущего доступного пространства.

POSIX предлагает дополнительно вычесть 2048, чтобы процесс мог значительно изменить свою среду. Быстрая оценка с помощью команды getconf:

 expr `getconf ARG_MAX` - `env|wc -c` - `env|wc -l` \* 4 - 2048

Самый надежный способ получение доступного в данный момент пространства заключается в проверке успешности работы exec() с увеличением длины аргументов до тех пор, пока она не завершится неудачей. Это может быть дорого, но, по крайней мере, вам нужно проверить только один раз, длина envp[] считается автоматически, и результат надежен.

Альтернативно, GNU autoconf check "проверяет максимальную длину аргументов командной строки...- можно использовать. Он работает очень похоже.

Однако это приводит к гораздо более низкому значению (это может быть только четвертая часть действительного значения) как по намерению, так и по соображениям простоты:

В цикле с увеличением n, проверка пытается exec() с длиной аргумента 2n (но не будет проверять для n выше 16, то есть 512kB). Максимальное значение-ARG_MAX/2, Если ARG_MAX-степень 2. Наконец, найденное значение делится на 2 (для безопасности), по причине того, что "компиляторы C++ могут использовать огромное количество дополнительных аргументов".

Фактическое значение

В Linux 2.6.23, это 1/4 размера стека. код ядра Для справки.

Может быть, я ошибаюсь, но я думаю, что argc и argv принадлежат __библиотеки libc_начало_главный в библиотеку libc.так.6
кто называет главной ?

Может быть полезно :)

main() не является особенным в отношении того, что он принимает. Особенным является волшебство, которое происходит до того, как main() вызывается в первый раз.

Вы можете позвонить main() с тем, что вы хотите ...

#include <stdio.h>

char longstring[1024000] = "foo";

int main(int argc, char **argv) {
  char *p = longstring;
  printf("main called with argc == %d", argc);
  if (argv) printf(" and a relevant argv");
  puts("");
  switch (argc) {
    case 1: main(2, NULL); break;
    case 2: main(3, &p); break;
    default: puts("Uff!"); break;
  }
  return 0;
}