You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中用fread读取链表结构体二进制文件遇段错误如何解决?

Ah, I see the issue here—your struct has pointer members (char *name and struct list_node *next), which is why directly using fread on the entire node is causing a segmentation fault. Let me break this down and show you how to fix it:

Why the Segmentation Fault Happens

When you write a struct with pointer members directly to a binary file using fwrite, you're not saving the actual data those pointers point to—you're saving the memory addresses of that data.

  • For char *name, the file will store the address where the string was located in your program's memory, not the string itself.
  • For struct list_node *next, it stores the address of the next node in the original linked list, which is meaningless in a new program run (that memory address might be used by something else entirely, or be invalid).

When you try to fread this back, those pointers will point to invalid memory locations. Accessing them (like trying to read the string via name) triggers a segmentation fault.

The Correct Approach: Serialize Your Data

Instead of writing the entire struct (pointers and all), you need to serialize the actual data:

  1. Write the non-pointer fields directly (number, year, money).
  2. For the string name, first write its length (so you know how much memory to allocate when reading), then write the string content itself.
  3. Skip writing the next pointer entirely—you'll rebuild the linked list structure when reading by creating new nodes and linking them together.
Example Code for Writing the File

First, here's how to properly write your linked list to movies.dat:

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

struct list_node{ 
    int number; 
    char *name; 
    int year; 
    float money; 
    struct list_node *next; 
}; 
typedef struct list_node node;

void write_movies(const char *filename, node *root) {
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
        perror("Failed to open file for writing");
        exit(EXIT_FAILURE);
    }

    node *current = root;
    while (current != NULL) {
        // Write non-pointer fields
        fwrite(&current->number, sizeof(int), 1, fp);
        fwrite(&current->year, sizeof(int), 1, fp);
        fwrite(&current->money, sizeof(float), 1, fp);

        // Write string length (including null terminator) and content
        size_t name_length = strlen(current->name) + 1;
        fwrite(&name_length, sizeof(size_t), 1, fp);
        fwrite(current->name, sizeof(char), name_length, fp);

        current = current->next;
    }

    fclose(fp);
}
Example Code for Reading the File

Now, here's how to read the file back and rebuild the linked list correctly:

node* read_movies(const char *filename) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        perror("Failed to open file for reading");
        exit(EXIT_FAILURE);
    }

    node *root = NULL;
    node **current_ptr = &root; // Use a double pointer to easily add nodes to the list

    while (1) {
        // Allocate memory for a new node
        node *new_node = malloc(sizeof(node));
        if (!new_node) {
            perror("Failed to allocate memory for node");
            exit(EXIT_FAILURE);
        }

        // Read non-pointer fields—break if we reach end of file
        if (fread(&new_node->number, sizeof(int), 1, fp) != 1) {
            free(new_node);
            break;
        }
        if (fread(&new_node->year, sizeof(int), 1, fp) != 1) {
            free(new_node);
            break;
        }
        if (fread(&new_node->money, sizeof(float), 1, fp) != 1) {
            free(new_node);
            break;
        }

        // Read string length, allocate memory, then read the string
        size_t name_length;
        if (fread(&name_length, sizeof(size_t), 1, fp) != 1) {
            free(new_node);
            break;
        }
        new_node->name = malloc(name_length);
        if (!new_node->name) {
            perror("Failed to allocate memory for movie name");
            free(new_node);
            exit(EXIT_FAILURE);
        }
        if (fread(new_node->name, sizeof(char), name_length, fp) != name_length) {
            free(new_node->name);
            free(new_node);
            break;
        }

        // Link the new node to the list
        new_node->next = NULL;
        *current_ptr = new_node;
        current_ptr = &new_node->next;
    }

    fclose(fp);
    return root;
}
Key Notes to Remember
  • Always check the return values of fread and fwrite—this ensures you catch partial reads/writes or end-of-file conditions.
  • Don't forget to free the memory you allocate for nodes and strings when you're done with the linked list to avoid memory leaks.
  • If your existing movies.dat was created by writing entire structs directly, it's invalid—you'll need to regenerate the file using the correct write function above.

内容的提问来源于stack exchange,提问作者Sophia Sideri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:00:36