尝试释放指针并关闭文件时发生 C 段错误和核心转储

问题描述 投票:0回答:1

您好,我正在尝试从文件中读取内容以制作电影链接列表。在读取文件函数结束时,当我尝试释放行指针并关闭文件时,我得到了段错误和核心转储。释放和文件关闭都会引起问题。我很欣赏一些见解。我需要任何图书馆吗? fopen 工作得很好。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct movie {
    char *title;
    char **languages;
    int year;
    double rating;
    struct movie *next;
};

struct movie *read_file(const char *filename);
struct movie *create_movie(const char *title, const char **languages, int year, double rating);
void append_movie(struct movie *head, struct movie *new_movie);
void free_movie(struct movie *movie);

int main() {
    const char *filename = "movies_sample_1.csv";
    struct movie *head = read_file(filename);

    while (head != NULL) {
        struct movie *temp = head;
        head = head->next;
        free_movie(temp);
    }

    return 0;
}

struct movie *read_file(const char *filename) {
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        perror("Error opening file");
        exit(1);
    }

    struct movie *head = NULL;
    char *line = NULL;
    size_t len = 0;
    ssize_t nread;

    if ((nread = getline(&line, &len, file)) == -1) {
        perror("Error reading header");
        exit(1);
    }

    while ((nread = getline(&line, &len, file)) != -1) {
        char *title = strtok_r(line, ",", &line);
        char *year_str = strtok_r(NULL, ",", &line);
        char *languages_str = strtok_r(NULL, ",", &line);
        char *rating_str = strtok_r(NULL, ",", &line);


        int year = atoi(year_str);
        double rating = atof(rating_str);

        const char *languages[10];
        int language_count = 0;
        char *language = strtok_r(languages_str, ";[]", &languages_str);

        while (language != NULL) {
            languages[language_count++] = language;
            language = strtok_r(NULL, ";[]", &languages_str);
        }

        languages[language_count] = NULL;

        struct movie *new_movie = create_movie(title, languages, year, rating);

        if (head == NULL) {
            head = new_movie;
        } else {
            append_movie(head, new_movie);
        }
    }

    // if (line != NULL) {
    //     free(line);
    // }

    //fclose(file);
    return head;
}

struct movie *create_movie(const char *title, const char **languages, int year, double rating) {
    struct movie *new_movie = (struct movie *)malloc(sizeof(struct movie));
    if (new_movie == NULL) {
        printf("Memory allocation failed");
        exit(1);
    }

    new_movie->title = strdup(title);
    if (new_movie->title == NULL) {
        printf("Memory allocation failed");
        exit(1);
    }

    new_movie->year = year;
    new_movie->rating = rating;

    int num_languages = 0;
    while (languages[num_languages] != NULL) {
        num_languages++;
    }

    new_movie->languages = (char **)malloc(sizeof(char *) * (num_languages + 1));
    if (new_movie->languages == NULL) {
        printf("Memory allocation failed");
        exit(1);
    }

    for (int i = 0; i < num_languages; i++) {
        new_movie->languages[i] = strdup(languages[i]);
        if (new_movie->languages[i] == NULL) {
            printf("Memory allocation failed");
            exit(1);
        }
    }

    new_movie->languages[num_languages] = NULL;
    new_movie->next = NULL;
    return new_movie;
}

void append_movie(struct movie *head, struct movie *new_movie) {
    struct movie *current = head;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = new_movie;
}

void free_movie(struct movie *movie) {
    free(movie->title);

    for (int i = 0; movie->languages[i] != NULL; i++) {
        free(movie->languages[i]);
    }

    free(movie->languages);
    free(movie);
}
c visual-studio segmentation-fault
1个回答
0
投票

可能还有更多问题,但这里至少有一个......

getline
将为
line
分配动态内存。您必须稍后通过调用
free(line)
来释放该内存。为此,您必须确保
line
未更改,即从
line
获取的值
getline
是要传递给
free
的值。

但是,你确实

    char *title = strtok_r(line, ",", &line);
    char *year_str = strtok_r(NULL, ",", &line);
    char *languages_str = strtok_r(NULL, ",", &line);
    char *rating_str = strtok_r(NULL, ",", &line);

因此

line
的值可能/将会改变,并且
free(line)
将失败。

© www.soinside.com 2019 - 2024. All rights reserved.