Search code examples
cpointersmallocstructuredouble-pointer

malloc(): corrupted top size on deleting an entry from binary file


I AM CREATING A SCHOOL MANAGEMENT SYSTEM . WHEN I TRY TO DELETE A STUDENT AFTER ADDING ONE I AM GETTING "malloc(): corrupted top size" ERROR .CANT FIND THE REASON.I AM A BEGINNER , HELP PLEASE

structure i created :

typedef struct {
    char name[NAME_LENGTH ];
    int age;
    int roll_no;
    char blood_group[BG_LENGTH];
} Student;

typedef struct {
    char school_name[NAME_LENGTH ];
    int classes;
    int *no_of_students;
    Student **students;
} School;

function to add student

void add_student(School *school, int class_id, int student_id)
{  
    if(school==NULL)
    {
        printf("\n INVALID SCHOOL POINTER\n");
        return;
    }
    if (class_id<0 || class_id >= school->classes )
    {
        printf("\nINVALID_CLASS_INDEX");
        return;
    }
    if (student_id<0 || student_id >= school->no_of_students[class_id] )
    {
        printf("\nINVALID STUDENT INDEX");
        return;
    }


    int roll_no;   

   printf("\nEnter roll number: ");    
     if (scanf("%d", &roll_no) != 1)
    {
        printf("\nInvalid input. Please enter a number.\n");
        clear_input_buffer();
        return;
        
    }
 load_students_from_bfile(school,  class_id,  student_id);



for (int i = 0; i < school->no_of_students[class_id]; i++) {
    // printf("Checking roll number at index %d: %d\n", i, school->students[class_id][i].roll_no);
    if (school->students[class_id][i].roll_no == roll_no) {
        printf("Found existing roll number: %d\n", roll_no);
        printf("Roll number already exists!\n");
        return;
    }
}
    school->students[class_id][student_id].roll_no = roll_no;
    printf("\nEnter student name: ");
    scanf(" %[^\n]", school->students[class_id][student_id].name);
    printf("\nEnter age: ");
    if (scanf("%d", &school->students[class_id][student_id].age) != 1)    {
        printf("\nInvalid input. Please enter a number.\n");
        clear_input_buffer();
        return;
    }  
int bg_choice;
printf("\nChoose your BloodGroup:\n\n1. A+\n2. A-\n3. B+\n4. B-\n5. AB+\n6. AB-\n7. O+\n8. O- \n\nYour Choice:  ");

if (scanf("%d", &bg_choice) != 1)
    {
        printf("\nInvalid input. Please enter a number.\n");
        clear_input_buffer();
        return;
    }     char bg[10];

    switch (bg_choice)
     {
     case 1:
     strcpy(bg,"A+");
     break;
     case 2:
     strcpy(bg,"A-");
     break;
     case 3:
     strcpy(bg,"B+");
     break;
     case 4:
     strcpy(bg,"B-");
     break;
     case 5:
     strcpy(bg,"AB+");
     break;
     case 6:
     strcpy(bg,"AB-");
     break;
     case 7:
     strcpy(bg,"O+");
     break;
     case 8:
    strcpy(bg,"O-");
    break;
     default:
   printf("\nInvalid Choice.\n");
             break;
    }
strcpy(school->students[class_id][student_id].blood_group,bg);
 printf("You choose blood_group : %s",school->students[class_id][student_id].blood_group);

    add_student_to_bfile(school,class_id,student_id);
}


void delete_student(School *school, int class_id, int roll_no) 
{
    if(school==NULL)
    {
        printf("\n INVALID SCHOOL POINTER\n");
        return;
    }
    if (class_id<0 || class_id > school->classes )
    {
        printf("\nINVALID_CLASS_INDEX");
        return;
    }
    if (roll_no<0 )
    {
        printf("\nINVALID ROLL NUMBER");
        return;
    }
 
    delete_student_from_bfile(school, class_id, roll_no) ;
}


3.MANAGE _ BINARYFILE.C


void load_from_bfile(School *school)
{
    if (school == NULL) {
        printf("\n INVALID SCHOOL POINTER");
        return;
        }
    FILE* bfptr=fopen("school.dat","rb");
    if(bfptr==NULL)
    {
        printf("\n not able to open file %s",strerror(errno));
        return;
    }
    
    int classes;
    char school_name[NAME_LENGTH];

    fread(&classes, sizeof(int), 1, bfptr);
    fread(school_name, sizeof(char), NAME_LENGTH, bfptr);
    strncpy(school->school_name, school_name, NAME_LENGTH);
    school->classes = classes;
    printf("******SCHOOL DETAILS******");
    printf("\nSchool Name: %s\n", school->school_name);
    printf("\nNumber of Classes: %d\n", classes);


        school->no_of_students = (int *)malloc(school->classes * sizeof(int));
        school->students = (Student **)malloc(school->classes * sizeof(Student *));


    for (int i = 0; i < classes; i++)
    {
        school->students[i] = (Student *)malloc(school->no_of_students[i] * sizeof(Student));

        int num_students;
        fread(&num_students, sizeof(int), 1, bfptr);
        school->no_of_students[i] = num_students;
        printf("\nClass %d - Number of Students: %d\n", i + 1, num_students);

     
    }

    fclose(bfptr);
}

void add_student_to_bfile(School *school, int class_id, int student_id)
{
    if(school==NULL)
    {
        printf("\n INVALID SCHOOL POINTER");
        return;
    }
   if (class_id<0 || class_id >= school->classes )
    {
        printf("\nINVALID_CLASS_INDEX");
        return;
    }
    if (student_id<0 || student_id >=school->no_of_students[class_id] )
    {
        printf("\nINVALID STUDENT INDEX");
        return;
    }


    char filename[20];
    sprintf(filename, "%d.bin", class_id+1); 
    FILE *bfptr = fopen(filename, "ab");
    if (bfptr == NULL)
    {
        printf("\nUnable to open file %s: %s\n", filename, strerror(errno));
        return;
    }

    fwrite(&school->students[class_id][student_id], sizeof(Student), 1, bfptr);

    fclose(bfptr);

    printf("\nStudent details added  successfully.\n");

}

void delete_student_from_bfile(School *school, int class_id, int target_rollno) 
{
    if(school==NULL)
    {
        printf("\n INVALID POINTER");
        return;
    }

    if (class_id > school->classes) {
        printf("\nInvalid class index");
        return;
    }

    char filename[20];
    

    sprintf(filename, "%d.bin", class_id); 
    FILE *bfptr = fopen(filename, "rb+");
    if (bfptr == NULL) {
        printf("\nUnable to open file %s: %s\n", filename, strerror(errno));
        return;
    }

    char temp_filename[20];
    sprintf(temp_filename, "%d.tmp", class_id);
    FILE *temp_bfptr = fopen(temp_filename, "wb+");
    if (temp_bfptr == NULL) {
        printf("\nUnable to create temporary file %s: %s\n", temp_filename, strerror(errno));
        fclose(bfptr);
        return;
    }

    Student student;
    int found = 0;
    int i=0;
    while (fread(&student, sizeof(Student), 1, bfptr) == 1) {
        i++;
        if (student.roll_no == target_rollno) {
            found = 1;
            printf("\nStudent with Roll No %d found and deleted.\n", target_rollno);
            for (int j = i; j < school->no_of_students[class_id] - 1; j++) {
                school->students[class_id][j] = school->students[class_id][j + 1];
            }

            school->no_of_students[class_id]--;
        } else {
            fwrite(&student, sizeof(Student), 1, temp_bfptr);
        }
    }

    if (!found) {
        printf("\nStudent with Roll No %d not found.\n", target_rollno);
    }

    fclose(bfptr);
    fclose(temp_bfptr);

    remove(filename); 
    rename(temp_filename, filename);
}

OUTPUT: TERMINAL OUTPUT SHOWING ERROR

IN MY CODE THE INPUTS ARE TAKEN USING STRUCTURES , THEN THEY ARE SAVED INTO A BINARY FILE ,SCHOOL RECORD HAS SEPARATE FILE,AND EACH CLASS HAS SEPARATE FILE.

NEED TO REMOVE THAT ERROR AND CORRECT MY CODE


Solution

  • In function load_from_bfile:

    for (int i = 0; i < classes; i++)
    {
        school->students[i] = (Student *)malloc(school->no_of_students[i] * sizeof(Student));
    
        int num_students;
        fread(&num_students, sizeof(int), 1, bfptr);
        school->no_of_students[i] = num_students;
        printf("\nClass %d - Number of Students: %d\n", i + 1, num_students);
    
     
    }
    

    The malloc call uses the value of school->no_of_students[i]. However, that value is only set a couple of lines later. At the point of use, it has no value yet.