链表初始化后调用ListLength触发Segmentation Fault的原因排查
嘿,你的链表初始化为啥触发Segmentation Fault?
我一眼就看出问题出在函数参数的传递方式上,咱们一步步拆解:
问题核心:值传递的“坑”
你写的InitList函数参数是LinkList L,而LinkList本质是LNode*(指针类型)。在C语言里,函数参数是值传递——也就是说,你调用InitList(L)时,只是把main里那个未初始化的L的垃圾值复制了一份给函数里的局部变量L。
你在InitList里给这个局部的L分配了内存:
L=(LinkList)malloc(sizeof(LNode));
但这个修改只在函数内部有效!函数执行完,局部变量销毁,main里的L还是原来那个野指针(指向随机内存地址)。等你调用ListLength(L)时,访问L->next就是在访问野指针的成员,直接触发段错误,完全合情合理。
两种靠谱的修复方案
方案一:用指针的指针传递(修改原指针)
把InitList的参数改成指针的指针(也就是LinkList *L),这样就能直接修改main里的L变量本身:
int InitList(LinkList *L){ *L=(LinkList)malloc(sizeof(LNode)); // 给main里的L分配内存 if(!*L)return 0; (*L)->next=NULL; // 注意括号优先级,先解引用再访问next return 1; }
然后main里调用的时候要传L的地址:
InitList(&L);
方案二:让InitList直接返回链表指针
更直观的方式是让InitList返回分配好的链表头指针,main里直接接收:
LinkList InitList(){ LinkList L=(LinkList)malloc(sizeof(LNode)); if(L){ L->next=NULL; } return L; }
main里改成:
LinkList L = InitList();
顺便优化下ListLength逻辑
你的ListLength里的if((L->next)==NULL) return 0;其实多余,直接用循环就能处理空链表的情况,逻辑更统一:
int ListLength(LinkList L) { int length=0; struct LNode *x = L->next; // 从第一个节点开始遍历 while(x){ length++; x=x->next ; } return length; }
空链表时x一开始就是NULL,循环不执行,直接返回0,完美。
完整修正后的代码(用方案一)
#include<stdio.h> #include<stdlib.h> typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; int InitList(LinkList *L); int ListLength(LinkList L); int main(void) { LinkList L; InitList(&L); printf("%d",ListLength(L)); // 别忘了释放内存,避免内存泄漏哦 struct LNode *tmp; while(L){ tmp = L; L = L->next; free(tmp); } return 0; } int InitList(LinkList *L){ *L=(LinkList)malloc(sizeof(LNode)); if(!*L)return 0; (*L)->next=NULL; return 1; } int ListLength(LinkList L) { int length=0; struct LNode *x = L->next; while(x){ length++; x=x->next ; } return length; }
内容的提问来源于stack exchange,提问作者Weng
相关产品推荐
相关产品推荐

