Может ли переполнение argc?

Я блуждал в SO и видел этот вопрос. Затем я начал задаваться вопросом, могу ли я переполнять argc.

Стандарт говорит, что argv[argc] должен быть нулевым указателем, но это будет false, если переполнение argc.

(I написал небольшую программу на C и python script для тестирования, но получил MemoryError.)

Спасибо!


Обоснование для международного стандарта - Языки программирования - C §5.1.2.2.1 Запуск программы

Спецификация argc и argv в качестве аргументов main распознает обширную практику. argv[argc] требуется, чтобы он был нулевым указателем, чтобы обеспечить избыточную проверку для конца списка, также на основе обычной практики.

Ответ 1

В соответствии со стандартом

Итак, из вашей цитаты:

argv[argc] требуется, чтобы он был нулевым указателем

Следовательно, argc не может переполняться, потому что указанное выше утверждение не будет истинным.

На практике

На практике общий размер аргументов, переданных программе, ограничен.

В моей системе Linux/x64:

$ getconf ARG_MAX
2097152

Следовательно, общий размер аргумента составляет около 2 мегабайт, а argc не может переполняться. Я считаю, что этот предел измеряет комбинацию общих данных в argv и окружающей среде. Если вы превысите этот предел при попытке выполнить команду, exec() завершится с ошибкой E2BIG. Из man 2 execve:

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

Я считаю, что ограничение в 2 мегабайта на моей системе относительно велико по сравнению с другими системами. Моя система OS X сообщает о пределе ~ 260 КБ.

Но что, если ARG_MAX были действительно большими?

Хорошо, предположим, что вы находитесь в старой/странной системе, поэтому int - 16 бит, а ARG_MAX - более 2 15 что в противном случае вполне разумно. Предположим, вы вызываете execve() с более чем двумя аргументами 15. Реализация имеет два варианта.

  • Это может позволить переполнению argc... в основном, отбрасывая ваши данные, гарантируя, что выполняемая вами программа выполняется в некоторых неожиданных и, вероятно, ошибочно, и нарушает стандарт C. Хуже всего, ошибка затихает, поэтому вы никогда не узнаете.

  • Или он может просто вернуть EOVERFLOW из execve(), сообщив вам, что он просто не может запустить изображение с таким количеством параметров. Теперь стандарты POSIX/SUS ничего не упоминают об этом результате ошибки... но я подозреваю, что это просто потому, что стандартные авторы никогда не ожидали, что ARG_MAX будет больше, чем INT_MAX.

Вариант № 2 является единственным разумным вариантом. Если ваша система каким-то образом выбирает вариант №1, то она сломана, и вы должны подать отчет об ошибке.

В качестве альтернативы вы можете попробовать запустить старую программу, скомпилированную для 16-разрядной системы, но вы запускаете ее через какой-то эмулятор или уровень совместимости. Я ожидал, что эмулятор или уровень совместимости выдаст сообщение об ошибке, если вы попытаетесь передать в программу более 2 параметров 15.

Ответ 2

На практике нет, вы не можете. Большинство систем устанавливают относительно низкий предел суммарного размера argv и envp. Пределы в десятки до низких сотен КБ нередки; см. http://www.in-ulm.de/~mascheck/various/argmax/ для достаточно полного перечисления ограничений на различные ОС.

Ответ 3

Я пробовал это:

test.c:

 ⚡⚡⚡  more test.c 
#include <stdio.h>
int main(int argc, char **argv)
{
    printf("argc = %d\n", argc);
    printf("Size of argc = %d\n", sizeof(argc));
    return 0;
}

Затем использовался большой zipfile

 ⚡⚡⚡  ls -h bigfile 
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile

Затем прочитайте файл как параметры для тестовой программы:

⚡⚡⚡  ./test $(more bigfile)

Результат:

5 minutes nothing happend, then everything froze

Затем я попробовал меньший файл:

 ⚡⚡⚡  ls -h notsobigfile 
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile

И:

 ⚡⚡⚡  ./test $(more notsobigfile)
bash: ./test: Argument list too long

Ответ 4

Как указано стандартом, argv [argc] должен быть допустимым значением.

Итак, если среда выполнения находится в такой ситуации, что она не может гарантировать этого, она не должна запускать программу.