Где ошибка? (Программа C не будет распечатывать содержимое динамического массива)

Задача состояла в том, чтобы прочитать первые 20 строк из определенного файла и отформатировать их, чтобы использовать только определенные части, следующим шагом было сохранить эти отформатированные строки в динамическом массиве (char ** str | указатель на указатель), отправить его в функцию и распечатайте его с помощью указанной функции

Вот основной код:

int main(int argc, char* argv[]){
    FILE* file = fopen("./passwd.txt", "r");  // open file

    if (!file)
    {
        perror("Error opening file");
        return 1;
    }
    char line [MAXCHARS];
    int counter = 0;
    char ** str;
    str = malloc(20  * sizeof (char*));
    while (fgets(line, MAXCHARS, file) && counter < 20) {
        char * position;
        if ((position = strchr(line,':'))){
            char * end_char;
            *position = 0;        //setting here the value 0, will terminate the string line (first column)
            if ((position = strchr(++position,':')) && (end_char = strchr(++position,':'))){ //increment the position to skip the second column
                *end_char = 0; //set the value 0 to end_char to terminate the string pointed by position
                char * temp_str = "\0";
                sprintf(temp_str, "{%d} - {%s}\n", atoi(position), line ); //concatenate line and userID into one string and store it into a temporary string
                *(str + counter) = malloc(sizeof (char) * strlen(temp_str)); //set the memory space for the temp_string into the array
                *(str + counter) =  temp_str; //copy the string into the array

            }
        }
        counter++;
    }

    printArray(str);

    fclose(file);
    if (line)
        free(line);


    return 0;
}

А вот функция печати:

void printArray(char ** array){
    for(int i = 0; i < 20; i++){
        printf("%s",*(array+i));
        free(*(array+i));
    }
    free(array);
}

Я не могу найти ошибку, код компилируется с

Process finished with exit code -1073741819 (0xC0000005)

Так что, по крайней мере, он компилируется, и я думаю, что это просто проблема с моими навыками обработки указателей, но я не могу найти ошибку.

Кто-нибудь может мне помочь?

sprintf(temp_str,... — вы печатаете в строковый литерал, что само по себе является неопределенным поведением, более того, весьма вероятно, что недоступный для записи буфер слишком короткий...
Aconcagua 21.03.2022 09:24
free(line); неправильно: вы не выделили line
Mathieu 21.03.2022 09:27

@Aconcagua, тогда как я могу сохранить с определенной строкой формата? потому что гугление всегда приводило меня к функции sprintf().

Simone Nardone 21.03.2022 09:32

@Mathieu, что бесплатно (строка) была частью предыдущей задачи, просто забыл ее удалить

Simone Nardone 21.03.2022 09:32

Для *(str + x) есть короткая рука: str[x] — но вы не копирование в str[counter], а вместо этого переназначаете временную строку, теряя указатель на только что выделенную временную, при этом массив будет содержать во всех полях один и тот же адрес tmp_str. Вместо этого вам нужно strcpy(str[counter], tmp_str) — или более эффективно: size_t len = strlen(tmp); malloc(tmp); memcpy(str[c], tmp, len + 1); избегать многократного рассмотрения нулевого символа (strlen и strcpy).

Aconcagua 21.03.2022 09:35

@SimoneNardone sprintf в порядке, а не в буфере. Вам необходимо выделить достаточно памяти, например. грамм. через char tmp_str[MaximumExpectedLength];. Спецификатор формата для строки может учитывать максимальную длину строки, если вы хотите быть в безопасности (предотвращая запись за пределы буфера).

Aconcagua 21.03.2022 09:38

Хорошо, спасибо большое всем, теперь я понял.

Simone Nardone 21.03.2022 09:45

Дополнительное примечание: в системе POSIX вы можете использовать strdup для удобства — обратите внимание, что тогда ваш код является переносимым нет (по крайней мере, до C23, который будет включать его).

Aconcagua 21.03.2022 09:47
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
9
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

в вашей программе 3 ошибки:

  1. используйте temp_str, которые не были выделены.

    char * temp_str = "\0";
    sprintf(temp_str, "{%d} - {%s}\n", atoi(position), line ); 
    
  2. сохранить temp_str адрес локального указателя в str+counter и использовать указатель после того, как он вышел из области действия в printArray => поведение undefined

  3. line не указатель, нельзя использовать free

    if (line)
    {
       free(line);
    }
    

давайте попробуем это. https://godbolt.org/z/7KPfnTEMY Я исправляю эти пункты

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

Simone Nardone 21.03.2022 09:40

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

Aconcagua 21.03.2022 09:44

И что еще хуже: str[counter] = malloc(); str[counter] = tmp_str; <- утечка памяти, теряется последний указатель на только что выделенную память.

Aconcagua 21.03.2022 09:48

@Aconcagua, да, спасибо, использование указателя, который вышел за рамки, - это UB. я исправлю это

long.kl 21.03.2022 09:49

@Aconcagua printArray освободит их.

long.kl 21.03.2022 09:53

@long.kl Не в исходной версии — адрес вновь выделенной памяти перезаписывается в выражении, сразу после присваивания tmp_strprintArray попытается освободить временную память (несколько раз!). Это меняется с вашей версией, где вы правильно strcpy данные из временной памяти в эту вновь выделенную память.

Aconcagua 21.03.2022 10:01

Другие вопросы по теме