使用MALLOC创建动态数组时SCANF触发未处理异常的问题求助
C语言动态数组分配与输入触发访问违例的问题修复
问题描述
使用malloc创建动态数组并通过scanf获取用户输入时,触发未处理异常:
Unhandled exception at 0x00007FFEE518D646 (ucrtbased.dll) in Project4STRUCTS.exe: 0xC0000005: Access violation writing location 0xFFFFFFFFCD7AE350
经调试初步定位到Input_Data函数,尝试调试排查及在线搜索后未找到匹配解决方案,完整代码如下:
#define _CRT_SECURE_NO_WARNINGS #define SIZE 3 #include<stdio.h> typedef struct student_init_data { int ID; int* StudentGradeArray; int NumOfExams; }Student_init_data; typedef struct student_processed_data { int ID; int StudentAvg; }Student_processed_data; typedef struct statistics { Student_processed_data* HIGH; Student_processed_data* LOW; int SizeofHIGH; int SizeofLOW; int Tavg; }Statistics; int* Input_Data(int Exams) { int i; int* arr = (int*)malloc(Exams * sizeof(int)); for (i = 0;i < Exams;i++) { printf("enter Grade: "); scanf("%d", &arr[i]); } return arr; } int Student_Average(int* GradeArray,int NumofExams) { int i; int avg=0; for (i = 0;i < NumofExams;i++) avg = avg + GradeArray[i]; avg = avg / NumofExams; return avg; } int Total_Average(Student_processed_data StudentAVG[SIZE], int NumofStudents) { int i; int avg = 0; for (i = 0;i < NumofStudents;i++) avg = avg + StudentAVG[i].StudentAvg; avg = avg / NumofStudents; return avg; } void Classification(Student_init_data InitStudentData[SIZE],Statistics *pStats) { int i; Student_processed_data StudentAVG[SIZE]; pStats->SizeofHIGH = 0; pStats->SizeofLOW = 0; for (i = 0;i < SIZE;i++) StudentAVG[i].ID = InitStudentData[i].ID; for (i = 0;i < SIZE;i++) { StudentAVG[i].StudentAvg = Student_Average(InitStudentData[i].StudentGradeArray, InitStudentData[i].NumOfExams); } pStats->Tavg = Total_Average(StudentAVG, SIZE); for (i = 0;i < SIZE;i++) { if (StudentAVG[i].StudentAvg >= pStats->Tavg) (pStats->SizeofHIGH)++; else (pStats->SizeofLOW)++; } pStats->HIGH = (Student_processed_data*)malloc((pStats->SizeofHIGH) * sizeof(Student_processed_data)); pStats->LOW = (Student_processed_data*)malloc((pStats->SizeofLOW) * sizeof(Student_processed_data)); for (i = 0;i < SIZE;i++) { if (StudentAVG[i].StudentAvg >= pStats->Tavg) (pStats->HIGH)[i] = StudentAVG[i];// High=pointer||same as High[i] else (pStats->LOW)[i] = StudentAVG[i];// HIGH={ID,AVG}, StudentAVG={ID,AVG} } } void Print_Tab(Statistics Stats) { int i; printf("Total Average is:%d ", Stats.Tavg); printf("\n %d number of students had AVG higher than TAVG:\n", Stats.SizeofHIGH); for (i = 0;i < Stats.SizeofHIGH;i++) { printf("ID:%d , AVG:%d | ", (Stats.HIGH)[i].ID, (Stats.HIGH)[i].StudentAvg); } printf("\n %d number of students had AVG lower than TAVG:\n", Stats.SizeofLOW); for (i = 0;i < Stats.SizeofLOW;i++) { printf("ID:%d , AVG:%d | ", (Stats.LOW)[i].ID, (Stats.LOW)[i].StudentAvg); } } void Free_Mem(Statistics* Pfreestat, Student_init_data* PfreeStudentData) { free(Pfreestat->LOW); free(PfreeStudentData->StudentGradeArray); free(Pfreestat->HIGH); } void main() { int i; Student_init_data StudentData[SIZE]; Statistics Stats; for (i = 0;i < SIZE;i++) { printf("\nEnter Stundent Num %d ID and Number of Exams:\n", i + 1); scanf("%d", &StudentData[i].ID); scanf("%d", &StudentData[i].NumOfExams); StudentData[i].StudentGradeArray = Input_Data(StudentData[i].NumOfExams); } Classification(StudentData ,&Stats); Print_Tab(Stats); Free_Mem(&Stats,&StudentData); }
问题根源分析
- 数组越界访问(核心问题):
Classification函数中,HIGH和LOW的分配大小是SizeofHIGH和SizeofLOW,但赋值时直接使用循环变量i(范围0到SIZE-1)作为索引。例如当SizeofHIGH=1时,i=2会访问HIGH[2],超出分配的内存范围,导致内存访问违例,这是触发异常的真正原因。 - malloc未做失败检查:
Input_Data和Classification中的malloc可能因内存不足返回NULL,直接访问NULL指针会触发异常。 - 内存泄漏与释放不完整:
Free_Mem仅释放了第一个学生的StudentGradeArray,其余学生的动态数组未释放,造成内存泄漏。 - 结构体未初始化:
main中的Statistics Stats未初始化,成员HIGH和LOW为野指针,存在潜在风险。 - 缺少stdlib.h头文件:
malloc和free函数需要该头文件支持,未包含可能导致未定义行为。
修复方案及代码
核心修复点:
- 为
HIGH和LOW分配后使用独立的索引变量,避免越界。 - 添加
malloc失败检查,空指针直接返回或终止程序。 - 修改
Free_Mem,循环释放所有学生的动态数组。 - 初始化
Statistics结构体,避免野指针。 - 补充
#include<stdlib.h>头文件。 - 规范
main函数返回值为int,符合C标准。
修复后的完整代码:
#define _CRT_SECURE_NO_WARNINGS #define SIZE 3 #include<stdio.h> #include<stdlib.h> typedef struct student_init_data { int ID; int* StudentGradeArray; int NumOfExams; }Student_init_data; typedef struct student_processed_data { int ID; int StudentAvg; }Student_processed_data; typedef struct statistics { Student_processed_data* HIGH; Student_processed_data* LOW; int SizeofHIGH; int SizeofLOW; int Tavg; }Statistics; int* Input_Data(int Exams) { if (Exams <= 0) { printf("Invalid number of exams\n"); return NULL; } int* arr = (int*)malloc(Exams * sizeof(int)); if (!arr) { printf("Memory allocation failed for grades\n"); return NULL; } int i; for (i = 0; i < Exams; i++) { printf("enter Grade: "); if (scanf("%d", &arr[i]) != 1) { printf("Invalid input, exiting\n"); free(arr); return NULL; } } return arr; } int Student_Average(int* GradeArray, int NumofExams) { int i; int avg = 0; for (i = 0; i < NumofExams; i++) avg += GradeArray[i]; avg /= NumofExams; return avg; } int Total_Average(Student_processed_data StudentAVG[SIZE], int NumofStudents) { int i; int avg = 0; for (i = 0; i < NumofStudents; i++) avg += StudentAVG[i].StudentAvg; avg /= NumofStudents; return avg; } void Classification(Student_init_data InitStudentData[SIZE], Statistics* pStats) { int i; Student_processed_data StudentAVG[SIZE]; int high_idx = 0, low_idx = 0; pStats->SizeofHIGH = 0; pStats->SizeofLOW = 0; for (i = 0; i < SIZE; i++) { StudentAVG[i].ID = InitStudentData[i].ID; StudentAVG[i].StudentAvg = Student_Average(InitStudentData[i].StudentGradeArray, InitStudentData[i].NumOfExams); } pStats->Tavg = Total_Average(StudentAVG, SIZE); for (i = 0; i < SIZE; i++) { if (StudentAVG[i].StudentAvg >= pStats->Tavg) pStats->SizeofHIGH++; else pStats->SizeofLOW++; } pStats->HIGH = (Student_processed_data*)malloc(pStats->SizeofHIGH * sizeof(Student_processed_data)); if (!pStats->HIGH) { printf("Memory allocation failed for HIGH group\n"); return; } pStats->LOW = (Student_processed_data*)malloc(pStats->SizeofLOW * sizeof(Student_processed_data)); if (!pStats->LOW) { printf("Memory allocation failed for LOW group\n"); free(pStats->HIGH); pStats->HIGH = NULL; return; } for (i = 0; i < SIZE; i++) { if (StudentAVG[i].StudentAvg >= pStats->Tavg) { pStats->HIGH[high_idx++] = StudentAVG[i]; } else { pStats->LOW[low_idx++] = StudentAVG[i]; } } } void Print_Tab(Statistics Stats) { int i; printf("Total Average is:%d\n", Stats.Tavg); printf("%d number of students had AVG higher than or equal to TAVG:\n", Stats.SizeofHIGH); for (i = 0; i < Stats.SizeofHIGH; i++) { printf("ID:%d , AVG:%d | ", Stats.HIGH[i].ID, Stats.HIGH[i].StudentAvg); } printf("\n%d number of students had AVG lower than TAVG:\n", Stats.SizeofLOW); for (i = 0; i < Stats.SizeofLOW; i++) { printf("ID:%d , AVG:%d | ", Stats.LOW[i].ID, Stats.LOW[i].StudentAvg); } printf("\n"); } void Free_Mem(Statistics* Pfreestat, Student_init_data* PfreeStudentData) { for (int i = 0; i < SIZE; i++) { if (PfreeStudentData[i].StudentGradeArray) { free(PfreeStudentData[i].StudentGradeArray); PfreeStudentData[i].StudentGradeArray = NULL; } } if (Pfreestat->HIGH) { free(Pfreestat->HIGH); Pfreestat->HIGH = NULL; } if (Pfreestat->LOW) { free(Pfreestat->LOW); Pfreestat->LOW = NULL; } } int main() { int i; Student_init_data StudentData[SIZE] = {0}; Statistics Stats = {NULL, NULL, 0, 0, 0}; for (i = 0; i < SIZE; i++) { printf("\nEnter Student Num %d ID and Number of Exams:\n", i + 1); if (scanf("%d%d", &StudentData[i].ID, &StudentData[i].NumOfExams) != 2) { printf("Invalid input, exiting\n"); Free_Mem(&Stats, StudentData); return 1; } StudentData[i].StudentGradeArray = Input_Data(StudentData[i].NumOfExams); if (!StudentData[i].StudentGradeArray) { Free_Mem(&Stats, StudentData); return 1; } } Classification(StudentData, &Stats); Print_Tab(Stats); Free_Mem(&Stats, StudentData); return 0; }
内容的提问来源于stack exchange,提问作者eyal gvili
相关产品推荐
相关产品推荐

