0

I'm using a function to create a dynamic array using MALLOC.

getting user input with the use of SCANF. for some reason I get this Error statement:

** Unhandled exception at 0x00007FFEE518D646 (ucrtbased.dll) in Project4STRUCTS.exe: 0xC0000005: Access violation writing location 0xFFFFFFFFCD7AE350.**

THE CODE

THE PROBLEM IS IN THE FUNCTION CALLED 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);




    

}

ERROR MESSAGE

Thank you all, Eyal

I tried debugging to see the problem, and couldn't get more than the understanding that the problem falls with the SCANF.

I tried looking into this certain exception online, couldn't find something with the same issue.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 1
    Welcome to SO. Please provide code and error messages as text, not as pictures. We cannot copy your screenshot into an editor or compiler. – Gerhardh Nov 18 '22 at 14:02
  • 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; – eyal gvili Nov 18 '22 at 14:03
  • https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors/285557#285557 – William Pursell Nov 18 '22 at 14:03
  • 1
    A good general rule: don't use scanf. Also, read http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html – William Pursell Nov 18 '22 at 14:03
  • Please put missing information into the question, not in comments. You can use the `edit` button below the question – Gerhardh Nov 18 '22 at 14:04
  • You do not check if you got valid memory address from `malloc`. Otherwise the code looks OK. – Gerhardh Nov 18 '22 at 14:05
  • thanks for answering, how do I check and how can i solve this ? @Gerhardh – eyal gvili Nov 18 '22 at 14:08
  • How you check if a variable has a certain value? With `==`: `if (arr == NULL) { /*error handling*/ } else { /*use arr*/ }` – Gerhardh Nov 18 '22 at 16:16

1 Answers1

0

Some problems:

  1. You should include #include <stdlib.h> for the memory management functions.
  2. Change Free_Mem(&Stats,&StudentData); to Free_Mem(&Stats,StudentData); because StudentData is an array of structs.
  3. Change free(PfreeStudentData->StudentGradeArray); to for (int i = 0; i < SIZE; i++) free(PfreeStudentData[i].StudentGradeArray);
  4. void main() is non-standard C. Better to use int main() and return 0 at completion.

Try with these changes.

  • thanks for replying. this didn't solve the problem on my end. when reaching the scanf it still shows me this exception also I didn't quite understand why it's not &Studentdata if it a struct and not a pointer – eyal gvili Nov 18 '22 at 14:28
  • It's becasue it's an array of structs. Also Free_Mem should loop over the array and free `StudentGradeArray` in each element. – Anthony Kelly Nov 18 '22 at 14:35
  • 1
    Do you get the error on the first scanf or after you entered some data? – Anthony Kelly Nov 18 '22 at 15:04
  • thanks for helping! This WORKED!! What I want to understand is, why did I need to add another library? and also when there's an array of structs do you 1. always use . (instead of ->) after indexing? 2. when you send an array of structs to a function - does it send the first address, the first struct in the array? @Ant – eyal gvili Nov 18 '22 at 15:46
  • 1
    @eyalgvili you did not add another library. You only added a missing header. You should get warnings about using function that was not declared previously. Function `malloc` returns a pointer but if you don't provide a prototype it is assumed that `int` is returned. Another chance to get a very helpful warning from your compiler but you silence it by adding a useless and actually harmfull cast `arr = (int*)malloc...` You should not cast the return value of `malloc` in C – Gerhardh Nov 18 '22 at 16:19
  • On your question about using . instead of ->, it's because you are already deferencing the pointer by using the array syntax []. – Anthony Kelly Nov 18 '22 at 16:24
  • @Gerhardh, thank you for adding your comment. Why is it harmful and useless to cast MALLOC? what should I do differently next time? – eyal gvili Nov 18 '22 at 18:43
  • @eyalgvili See [Do I cast the result of malloc?](https://stackoverflow.com/a/605856/2410359). `arr = (int*)malloc(Exams * sizeof(int));` --> `arr = malloc(sizeof arr[0] * Exams);`. – chux - Reinstate Monica Nov 18 '22 at 19:22
  • @eyalgvili You should simply not cast return value of `malloc`. That's it. If you don't do this, the compiler will warn you about "making a pointer from an integer". That should make you look closer until you fixed that warning. Your cast prevented this warning. You did not look closer, you did not avoid the compiler doing some conversion it should not do. And as a result you got some crash. – Gerhardh Nov 18 '22 at 20:40