Ошибка сегмента при чтении строки в динамически размещенный массив указателей символов - PullRequest
0 голосов
/ 19 февраля 2019

В C я пытаюсь реализовать функцию, которая использует getline() для чтения всех строк из файла.Он реализован аналогично getline(), в частности тот факт, что он использует realloc() для изменения размера char**, если недостаточно памяти, выделенной для хранения следующего указателя на строку.К сожалению, я получаю ошибки seg во время процесса дублирования строки.

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

ssize_t fgetlines(char*** linesptr, size_t* n, FILE* fp)
{
    char* line = NULL;
    size_t sz_line = 0;
    size_t cur_len = 0;
    size_t needed;

    if (linesptr == NULL || n == NULL) {
        errno = EINVAL;
        return -1;
    }

    if (*linesptr == NULL) {
        if (*n == 0)
            *n = sizeof(**linesptr) * 30; /* assume 30 lines */
        *linesptr = malloc(*n);
        if (*linesptr == NULL) {
            *n = 0;
            return -1;
        }
    }

    while (getline(&line, &sz_line, fp) > 0) {
        needed = (cur_len + 1) * sizeof(**linesptr);
        while (needed > *n) {
            char** new_linesptr;
            *n *= 2;
            new_linesptr = realloc(*linesptr, *n);
            if (new_linesptr == NULL) {
                *n /= 2;
                free(line);
                return -1;
            }
            *linesptr = new_linesptr;
        }
        *linesptr[cur_len] = strdup(line);
        printf("%s", *linesptr[cur_len]);
        if (*linesptr[cur_len] == NULL) {
            free(line);
            free(*linesptr);
            return -1;
        }
        ++cur_len;
    }

    free(line);
    return cur_len;
}

И я вызываю функцию так:

    char **settings = NULL;
    size_t sz_settings = sizeof(*settings) * 6;
    int count = fgetlines(&settings, &sz_settings, f_cfg);

Из-за невозможности успешного завершения функции я не получаю никакого вывода.Но после печати строки после strdup() мне удалось получить одну строку f_cfg, "Hello World" до ошибки сегмента.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Должен измениться

*linesptr[cur_len]  =>  (*linesptr)[cur_len]

Измененная функция выглядит следующим образом:

ssize_t fgetlines(char *** linesptr, size_t *n, FILE *fp)
{
    char *line = NULL;
    size_t sz_line = 0;
    size_t cur_len = 0;
    size_t needed;

    if (linesptr == NULL || n == NULL) {
        errno = EINVAL;
        return -1;
    }

    if (*linesptr == NULL) {
        if (*n == 0)
            *n = sizeof(**linesptr) * 30; /* assume 30 lines */
        *linesptr = malloc(*n);
        if (*linesptr == NULL) {
            *n = 0;
            return -1;
        }
    }

    while (getline(&line, &sz_line, fp) > 0) {
        needed = (cur_len + 1) * sizeof(**linesptr);
        while (needed > *n) {
            char **new_linesptr;
            *n *= 2;
            new_linesptr = realloc(*linesptr, *n);
            if (new_linesptr == NULL) {
                *n /= 2;
                free(line);
                return -1; // Possible memory leak
            }
            *linesptr = new_linesptr;
        }
        (*linesptr)[cur_len] = strdup(line);
        printf("%s", (*linesptr)[cur_len]);
        if ((*linesptr)[cur_len] == NULL) {
            free(line);
            free(*linesptr);
            return -1;  // Possible memory leak
        }
        ++cur_len;
    }

    free(line);
    return cur_len;
}

Кроме того, при неудачном выделении памяти память «strdup» не свободна, чтоприведет к утечке памяти.

0 голосов
/ 19 февраля 2019

Как указал chux, предполагаемый приоритет здесь был неправильным.Ссылки на *linesptr[cur_len] должны быть изменены на (*linesptr[cur_len]).Также исправлена ​​дыра в коде *n == 0 and *n *= 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...