C语言结构体Library初始化后仅首元素可访问,其余触发Segmentation Fault
问题分析与修复
嘿,咱们来拆解下你遇到的段错误问题——核心原因是你对library结构体里的booklist数组的初始化逻辑完全错了,导致除第一个元素外,剩下的都是野指针,访问自然触发了内存权限错误。
问题到底出在哪?
你的lib结构体里,booklist是一个book*类型的数组(book* booklist[MAXBOOKS]),意思是数组里每个位置都要存放一个指向book对象的指针。但你初始化时写的{3,{list}},只是把malloc出来的book数组的首地址赋值给了booklist[0],booklist[1]和booklist[2]根本没被初始化,还是随机的垃圾值——也就是野指针。当printLibrary循环到i=1和i=2时,访问这些野指针指向的内存,直接就触发段错误了。
另外还有个隐藏坑:你的storeBook函数完全起不了作用,就算调用也会出问题——因为你传的是library的副本(值传递),函数里修改的只是副本的booklist,原结构体根本没变化;而且CurrentBook是函数的局部变量,函数结束后它的内存会被释放,你把它的地址存在booklist里,后续访问也是非法内存。
修复后的代码方案
咱们直接修正初始化逻辑,同时顺便把storeBook的坑也填上:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXBOOKS 10 typedef struct books { char* title; char* author; int id; } book; typedef struct library { int number_of_books; book* booklist[MAXBOOKS]; } lib; // 修改为传指针,避免值传递的副本问题,同时传入合法的book指针 void storeBook(lib* library, book* CurrentBook) { // 先检查图书馆有没有空位 if (library->number_of_books < MAXBOOKS) { library->booklist[library->number_of_books] = CurrentBook; library->number_of_books++; } } void printLibrary(lib library) { for(int i = 0; i < library.number_of_books; i++) { printf("Book %d:\nTitle: %s\nAuthor: %s\nID: %d\n\n", i+1, library.booklist[i]->title, library.booklist[i]->author, library.booklist[i]->id); } } int main() { book b_1 = {"The trial","Kafka",101}; book b_2 = {"The lurking fear","Lovecraft",102}; book b_3 = {"Dora's storytime collection","Valdes",103}; // 方法1:直接用栈上book对象的地址初始化booklist(最简单的方式) lib CurrentLibrary = { 3, {&b_1, &b_2, &b_3} // 每个元素都指向对应的合法book对象 }; // 方法2:如果想用malloc的数组,需要循环给booklist每个元素赋值 /* book* list = (book*)malloc(3*sizeof(book)); list[0] = b_1; list[1] = b_2; list[2] = b_3; lib CurrentLibrary = {3, {}}; // 先初始化空数组 for (int i=0; i<3; i++) { CurrentLibrary.booklist[i] = &list[i]; // 逐个指向malloc数组里的对应book } */ printLibrary(CurrentLibrary); // 如果用了malloc,记得最后释放内存避免泄漏 // free(list); return 0; }
关键说明
booklist的正确初始化:要么直接把栈上b_1/b_2/b_3的地址逐个放进数组,要么用malloc数组时,循环把&list[i]赋值给booklist[i],确保每个元素都是合法指针。- 值传递的坑:修改结构体的函数一定要传指针,否则修改的只是副本,原对象不会有变化;同时绝对不要存储局部变量的地址,要传栈或堆上长期存在的对象指针。
- 内存管理:如果用了
malloc分配内存,记得最后用free释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Michael Bohanan
相关产品推荐
相关产品推荐

