int     main(int    argc, char* argv[])
{
    int num = atoi(argv[1]);

    if (argc < 2 || argc > 3) {
        fprintf(stderr, "Usage:\tpartner1 (nameIndex)\n");
        exit(EXIT_FAILURE);
    }
    if (num < 0 || num > 2) {
        printf("nameIndex must be in[0, 1, 2]");
        exit(EXIT_FAILURE);
    }

вывод

./parent1

Segmentation fault

Я получаю ошибку сегментации, и я не уверен, почему это происходит. Я знаю, что второй оператор if работает нормально, потому что если я ввожу ./partner1 4 или ./partner1 -1, вывод будет

nameIndex must be in[0, 1, 2]

Почему это происходит?

Благодарность

c
0
DO HWI LEE 3 Фев 2022 в 23:06
7
Без дополнительных аргументов командной строки argv[1] будет NULL. Эта строка должна появиться только после того, как вы проверили количество аргументов.
 – 
Thomas Jager
3 Фев 2022 в 23:07
2
Не пытайтесь получить доступ к большему количеству аргументов в argv, чем указано в количестве argc.
 – 
jarmod
3 Фев 2022 в 23:07
Вам нужно #include <stdio.h> и #include <stdlib.h>, а также в вашей программе отсутствует } в конце, поэтому она даже не должна компилироваться.
 – 
Ted Lyngmo
3 Фев 2022 в 23:14
О, ничего себе, я переключил линию, как вы сказали, и она работает. Спасибо!
 – 
DO HWI LEE
3 Фев 2022 в 23:16
Пожалуйста, дайте ответ.
 – 
Yunnosch
3 Фев 2022 в 23:18

2 ответа

Лучший ответ

Переместите int num = atoi(argv[1]); ниже отметки argc. Таким образом, вы будете проверять argv[1], только если знаете, что он существует.

int     main(int    argc, char* argv[])
{
    if (argc < 2 || argc > 3) { 
        fprintf(stderr, "Usage:\tpartner1 (nameIndex)\n");
        exit(EXIT_FAILURE);
    }

    int num = atoi(argv[1]);

    if (num < 0 || num > 2) {
        printf("nameIndex must be in[0, 1, 2]");
        exit(EXIT_FAILURE);
    }
1
yhyrcanus 3 Фев 2022 в 23:52

Аргумент argv функции main является указателем на массив argc указателей на строки, за которым следует указатель NULL. argv[0] указывает на C-строку имени программы, а argv[1] на argv[argc - 1] будет указывать на аргументы командной строки.

Например, если вы выполняете такую ​​программу, как ./program hello world, argc будет 3, а argv будет указателем на массив, который выглядит так:

+------------------------+----------------------+----------------------+------+
| <pointer to "program"> | <pointer to "hello"> | <pointer to "world"> | NULL |
+------------------------+----------------------+----------------------+------+

Если вы подтвердили, что argc == 3, то вы знаете, что можете получить доступ к строкам, на которые указывают argv[0], argv[1] и argv[2].

Без аргументов, выполнив ./program, вы получите что-то вроде:

+------------------------+------+
| <pointer to "program"> | NULL |
+------------------------+------+

Вы можете видеть, что argv[1] — это указатель NULL, который нельзя разыменовать (вы не можете получить доступ к данным, на которые он указывает).

Функция atoi получит доступ к строке, на которую указывает аргумент, и это не может быть NULL.

Вы всегда должны проверять значение argc и/или последовательно проходить через массив argv, проверяя NULL. Ваш код получит доступ к argv[1] до того, как проверит значение argc, что вызовет разыменование указателя NULL, что приведет к сбою.

Строка с atoi должна быть перемещена после точки, где вы отметили argc.

0
Thomas Jager 3 Фев 2022 в 23:57