Почему ошибка сегментации после изменения указателя на структуру? - PullRequest
0 голосов
/ 03 октября 2019

В настоящее время у меня есть работающий код, и когда я пытался сделать функцию из преобразования файла в массив, я получаю ошибку сегментации. Я знаю, что объекты внутри fileToArray являются правильными (что касается объектов myData), потому что когда внутри функции, myData.length и myData.array все возвращаются правильно. Однако после ссылки на указатель в основном я получаю ошибку сегмента. Я новичок в c, но все это работает без определенного указателя на структуру.

Итак, если я вызываю эту программу с аргументом в файле с несколькими строками текста, происходит сбой набора.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>

typedef struct {
    int length;
    char** array;
} FileStruct;

void fileToArray(FileStruct* fileDataPtr, int argc, char *argv[]){
    int  fd, i, n, count;
    struct stat statbuf;
    char *buf, *inbuf, *str, *saveptr;
    char **array;

    if ((fd = open(argv[1], O_RDONLY)) == -1) {
        printf("Error opening file %s\n", argv[1]);
        exit (-1);
    }

    if (lstat(argv[1], &statbuf) < 0) {
        printf("Unable to lstat file %s\n", argv[1]);
        exit (-1);
    }
    off_t filesize = statbuf.st_size;
    buf = malloc(sizeof(char)*filesize);
    array = malloc(sizeof(char *)*filesize);

    count = 0;
    if ((n = read(fd, buf, filesize)) > 0){
        inbuf = buf;
        for (i = 1; ; inbuf = NULL, i++) {
            str = strtok_r(inbuf, "\n", &saveptr); 
            if (str == NULL)
               break;
            array[count] = malloc(sizeof(char)*(strlen(str)+1));
            strcpy(array[count++], str);
        }
    } else {
        printf("Error reading input file\n");
        exit (-1);
    }

    close(fd);

    // I know array works because it prints correctly here.
    for (i = 0; i < count; i++) {
    printf("%s\n", array[i]);
    free(array[i]);
    }

    fileDataPtr->length = count;
    fileDataPtr->array = array;

    free(array);
    free(buf);
}

int main(int argc, char *argv[]) {
    int i;

    FileStruct myData;
    FileStruct* fileDataPtr = &myData;
    fileToArray(fileDataPtr, argc, argv);

    printf("length: %i", myData.length);

    // I know this doesn't work because anything related to myData causes Seg fault.
    // for (i = 0; i < 1; i++) {
    //     printf("%s\n", myData.array[i]);
    //     free(myData.array[i]);
    // }

    return 0;
}

1 Ответ

1 голос
/ 03 октября 2019

В конце fileToArray вы назначаете array на fileDataPtr->array, затем на следующей строке вы освобождаете array. Это оставит fileDataPtr->array, указывающий на свободную память (висящий указатель). Когда вы разыменовываете его позже, вы переходите к неопределенному поведению, и может произойти все что угодно.

Поскольку назначение передает владение выделенной памятью fileDataPtr, вам не нужно освобождать array перед возвратом из fileToArray.

Удалить строку free(array);.

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