CS50 Lab血型遗传实验触发segmentation fault错误排查
CS50血型遗传模拟程序段错误修复
问题现象
- 程序运行触发
segmentation fault(段错误),报错指向代码第56行 - Valgrind内存检测提示存在8字节未初始化值被访问,该未初始化值由
create_family函数内的malloc堆分配产生
错误根因
代码一共存在3处逻辑错误,直接触发崩溃和内存问题:
- 递归创建父代节点后,未将父代指针赋值给当前节点的
parents数组成员。malloc分配的内存不会自动初始化成员值,p->parents[0]、p->parents[1]是存储随机垃圾值的野指针,直接解引用访问就会触发未初始化内存访问、野指针崩溃,这也是Valgrind报错的核心原因。 create_family函数末尾错误返回NULL,没有返回新创建的节点指针,导致main函数拿到的根节点指针为空,后续打印、释放内存的操作全部异常。free_family函数的递归释放逻辑有缺陷:仅判断p->parents[0]非空时才递归释放两个父节点,会出现父节点内存漏释放的问题。
修复代码
1. 补全父代指针赋值逻辑
在create_family的generations > 1分支中,递归生成父代节点后,先把父代指针存入当前节点的parents成员,再读取等位基因:
if (generations > 1) { person *person0 = create_family(generations - 1); person *person1 = create_family(generations - 1); // 补全:将父代指针绑定到当前节点 p->parents[0] = person0; p->parents[1] = person1; // 随机继承父母的等位基因 p->alleles[0] = p->parents[0]->alleles[rand() % 2]; p->alleles[1] = p->parents[1]->alleles[rand() % 2]; }
2. 修正create_family返回值
将函数末尾的返回语句从return NULL;改为返回实际创建的节点:
// 返回新创建的人员节点 return p;
3. 修复free_family递归逻辑
去掉多余的父节点非空判断,直接递归释放两个父节点即可,函数入口的base case已经处理了空指针场景:
void free_family(person *p) { if (p == NULL) { return; } // 直接递归释放双亲,无需提前判空 free_family(p->parents[0]); free_family(p->parents[1]); // 释放当前节点 free(p); }
报错对应说明
Valgrind提示的8字节未初始化值,对应64位系统下指针类型的长度,正好对应未赋值的p->parents数组成员。报错指向的代码行就是首次解引用未初始化父指针的位置,野指针指向非法内存地址,直接触发段错误。
内容的提问来源于stack exchange,提问作者jdog
相关产品推荐
相关产品推荐

