You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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);

}

问题根源分析

  1. 数组越界访问(核心问题):Classification函数中,HIGH和LOW的分配大小是SizeofHIGH和SizeofLOW,但赋值时直接使用循环变量i(范围0到SIZE-1)作为索引。例如当SizeofHIGH=1时,i=2会访问HIGH[2],超出分配的内存范围,导致内存访问违例,这是触发异常的真正原因。
  2. malloc未做失败检查:Input_Data和Classification中的malloc可能因内存不足返回NULL,直接访问NULL指针会触发异常。
  3. 内存泄漏与释放不完整:Free_Mem仅释放了第一个学生的StudentGradeArray,其余学生的动态数组未释放,造成内存泄漏。
  4. 结构体未初始化:main中的Statistics Stats未初始化,成员HIGH和LOW为野指针,存在潜在风险。
  5. 缺少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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:45:37