Я читал, что после того, как exec создает новый процесс,
argv is an array of argument strings, with
argv[argc] == 0
Что произойдет, если одно из других значений в массиве argv окажется равным 0? Будет ли неправильно вычисляться количество аргументов (argc) при запуске дочернего процесса?
Я прочитал это на странице 34 ABI AMD64 (https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf).





Системный вызов execve (который используется всеми функциями exec*) имеет аргумент в форме char *const argv[]. Ядро вычисляет argc, перебирая предоставленный argv как следует:
static int count(struct user_arg_ptr argv, int max)
{
int i = 0;
if (argv.ptr.native != NULL) {
for (;;) {
const char __user *p = get_user_arg_ptr(argv, i);
if (!p)
break;
if (IS_ERR(p))
return -EFAULT;
if (i >= max)
return -E2BIG;
++i;
if (fatal_signal_pending(current))
return -ERESTARTNOHAND;
cond_resched();
}
}
return i;
}
Функция get_user_arg_ptr по существу вычисляет индекс в массиве argv и возвращает указатель, хранящийся в этом индексе. Цикл прерывается при четырех условиях, два из которых имеют отношение к вашему вопросу:
NULL видел в массиве argv. Если после первого NULL в argv есть другие указатели, они игнорируются. Наличие более одного NULL пахнет ошибкой в программе, построившей argv.MAX_ARG_STRINGS, то есть определенный как 0x7FFFFFFF. В этом случае системный вызов не выполняется.Возвращенное значение i присваивается argc, когда возвращается get_user_arg_ptr.
Другой случай, когда завершение NULL в argv имеет значение, - это когда само приложение использует argv следующим образом:
for(char **p = argv; *p != NULL; ++p)
{
// ...
}
argv завершается NULL как часть Linux ABI, поэтому такой код является законным и переносимым для всех реализаций Linux. Кстати, этот код разрешен и в Windows. Поэтому argc предоставляется только для удобства.
Кроме того, стандарты C и C++ заявляют в 5.1.2.2.1 и 3.6.1 соответственно, что если argc больше нуля, то все значения в argv[0] - argv[argc-1] должны быть ненулевыми указателями на строки с завершающим нулем. Также argv[argc] должен быть нулевым и этот argc неотрицателен. См. Также ответ это.