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:
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.
Instead of writing the entire struct (pointers and all), you need to serialize the actual data:
- Write the non-pointer fields directly (
number,year,money). - For the string
name, first write its length (so you know how much memory to allocate when reading), then write the string content itself. - Skip writing the
nextpointer entirely—you'll rebuild the linked list structure when reading by creating new nodes and linking them together.
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(¤t->number, sizeof(int), 1, fp); fwrite(¤t->year, sizeof(int), 1, fp); fwrite(¤t->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); }
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; }
- Always check the return values of
freadandfwrite—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.datwas 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

