Ручка argc равна 0

Недавно я увидел что-то любопытное. В исходном коде HHVM первые три строки функции main() читаются следующим образом:

if (!argc) {
  return 0;
}

Это немного глупо, но все же, я просто не могу не задаваться вопросом... зачем возвращать 0!? Это не то, что я думаю, что есть правильный способ справиться с этим, но возвращение 0, обычно связанное с успехом, кажется особенно неуместным.

Кроме того, чтобы не сбой, существует ли когда-либо случай, когда соответствующий ответ на argc равен 0? (Или даже меньше 0?) Имеет ли значение?

Единственный способ, которым я знаю, в случае с argc 0 - с exec() и друзьями. Если по какой-то причине это случается, это почти наверняка ошибка в вызывающем, и вызываемый не может многое сделать.

(помечены как C и С++, потому что я ожидаю, что ответ будет одинаковым для двух языков)

Изменить: Чтобы сделать вопрос менее расплывчатым и философским, я предложу альтернативу.

if (!argc) {
  puts("Error: argc == 0");
  return 1;
}

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

Ответ 1

Я думаю, что это просто случай Оборонительное программирование из-за следующего фрагмента в HHVM (файл hphp/hhvm/main.cpp):

int main(int argc, char** argv) {
  if (!argc) {
    return 0;
  }
  HPHP::checkBuild();
  int len = strlen(argv[0]);

В строке:

int len = strlen(argv[0]);

если argc == 0argv[0] == NULL и strlen(argv[0]) вызовет ошибку сегментации.

Я не знаком с HHVM, но они могут просто предположить, что какая-то программа может вызывать программу без аргументов (даже название программы).

Ответ 2

Обратите внимание, что стандарт C11 явно допускает argc == 0:

5.1.2.2.1 Запуск программы

¶1 Функция, вызванная при запуске программы, называется main. Реализация не объявляет прототип для этой функции. Он определяется с типом возврата int и без Параметры:

int main(void) { /* ... */ }

или с двумя параметрами (называемыми здесь argc и argv, хотя любые имена могут быть используются, поскольку они являются локальными для функции, в которой они объявлены):

int main(int argc, char *argv[]) { /* ... */ }

или эквивалент; 10) или каким-либо другим способом реализации.

¶2 Если они объявлены, параметры функции main должны подчиняться следующим Ограничения:

  • Значение argc должно быть неотрицательным.
  • argv[argc] должен быть нулевым указателем.
  • Если значение argc больше нуля, элементы массива argv[0] через argv[argc-1] включительно должны содержать указатели на строки, которые указаны определяемые реализацией значения среды хоста перед запуском программы. Цель состоит в том, чтобы предоставить информацию о программе, определенную до запуска программы из другого места в размещенной среде. Если хост-среда не способна снабжая строки буквами в верхнем и нижнем регистре, реализация должен гарантировать, что строки принимаются в нижнем регистре.
  • Если значение argc больше нуля, строка, на которую указывает argv[0]представляет собой название программы; argv[0][0] должен быть нулевым символом, если имя программы недоступно из среды хоста. Если значение argc равно больше единицы, строки, на которые указывает argv[1] через argv[argc-1]представляют параметры программы.
  • Параметры argc и argv, а строки, на которые указывает массив argv, должны могут быть модифицированы программой и сохраняют свои последние сохраненные значения между программой запуск и завершение программы.

10) Таким образом, int можно заменить на имя typedef, определенное как int, или тип argv можно записать как char ** argv и т.д.

Две пулевые точки, говорящие "если значение argc больше нуля", явно позволяют argc == 0, хотя для этого было бы необычно.

Теоретически, поэтому программа может принять меры предосторожности против нее, хотя argv[0] == 0, даже если argc == 0, так что, пока код не разыскивает нулевой указатель, это должно быть хорошо. Многие программы, возможно, даже большинство, не принимают таких мер предосторожности; они предполагают, что argv[0] не будет нулевым указателем.