指针数组首行打印异常求助:结构体读取数据文件问题排查
问题分析与修复方案
1. 首行乱码/垃圾值的根源与修复
你的代码存在严重的内存越界访问,这是触发乱码和未定义行为的核心原因:
- 你为
studentDataBase的每行仅分配了6个student*的存储空间(malloc(6*sizeof(student*))),但后续循环给第0行的studentDataBase[0][i]赋值时,i的范围是0到18(共19个元素),远超每行6个的容量,直接非法访问堆内存,破坏内存结构,导致乱码和垃圾数值。 - 同时,循环
for(int j=1;j<studentcount;j++)将studentDataBase[0][i]赋值给studentDataBase[j][i]时,i同样超出每行6个元素的范围,进一步加剧内存越界问题。
修复方式
当前三维数组的设计冗余且逻辑混乱,若仅需存储一组学生数据,直接简化为一维指针数组即可:
// 替换原三维数组定义 student** studentData; // 在main中分配内存 studentData = (student**)malloc(studentcount * sizeof(student*)); for(int i=0; i<studentcount; i++){ studentData[i] = NULL; }
随后将所有studentDataBase[0][i]替换为studentData[i],删除多余的行复制逻辑(若无需多份数据副本)。
2. 内存泄漏的修复
当前代码仅释放了顶层的studentDataBase指针,完全未释放下层内存块,需按从底层到顶层的顺序逐层释放:
正确释放流程(针对简化后的一维数组)
- 遍历每个学生结构体,先释放
first和last字符串 - 释放学生结构体本身
- 释放顶层的指针数组
示例代码:
// 逐层释放内存 for(int i=0; i<studentcount; i++){ free(studentData[i]->first); free(studentData[i]->last); free(studentData[i]); } free(studentData);
若坚持使用原三维数组设计,需先遍历所有有效行和列,释放每个学生的字符串和结构体,再释放每行的指针数组,最后释放顶层数组。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include "student.h" #include "bubble.h" #include <string.h> #include <assert.h> void printStudent(student *studentData) { printf("%s, %s: %d, %d, %d\n", studentData->last, studentData->first, studentData->exam1, studentData->exam2, studentData->exam3); } void printData(student *students[], int studentcount) { int i; for(i=0;i<studentcount;i++) printStudent(students[i]); } int main() { int studentcount = 19; char className[10]; char tempFirst[50]; char tempLast[50]; scanf("%s", className); printf("%s\n", className); // 简化为一维指针数组存储学生数据 student** studentData = (student**)malloc(studentcount * sizeof(student*)); for(int i=0; i<studentcount; i++){ studentData[i] = NULL; } for(int i=0;i<studentcount;i++) { studentData[i] = (student*)malloc(sizeof(student)); scanf("%s %s %d %d %d" ,tempFirst, tempLast ,&studentData[i]->exam1, &studentData[i]->exam2, &studentData[i]->exam3); studentData[i]->first = (char*)malloc(strlen(tempFirst)+1); strcpy(studentData[i]->first, tempFirst); studentData[i]->last = (char*)malloc(strlen(tempLast)+1); strcpy(studentData[i]->last, tempLast); } printData(studentData, studentcount); // 逐层释放内存 for(int i=0; i<studentcount; i++){ free(studentData[i]->first); free(studentData[i]->last); free(studentData[i]); } free(studentData); return 0; }
额外注意事项
- 确保
student.h中的student结构体包含char* first、char* last、int exam1、int exam2、int exam3字段 - 使用
scanf读取字符串时,建议用%49s限制长度,避免缓冲区溢出 - 可添加空指针检查(如
assert(studentData[i] != NULL)),确保malloc调用成功
内容的提问来源于stack exchange,提问作者Dax
相关产品推荐
相关产品推荐

