Malloc(): поврежден верхний размер при удалении записи из двоичного файла

Я СОЗДАЮ СИСТЕМУ УПРАВЛЕНИЯ ШКОЛОЙ. КОГДА Я ПЫТАЮСЬ УДАЛИТЬ СТУДЕНТА ПОСЛЕ ЕГО ДОБАВЛЕНИЯ, Я ПОЛУЧАЮ ОШИБКУ «malloc(): поврежден верхний размер». НЕ МОГУ НАЙТИ ПРИЧИНУ. Я НАЧИНАЮЩИЙ, ПОМОГИТЕ, ПОЖАЛУЙСТА.

структура, которую я создал:

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;

функция добавления студента

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);
}

ВЫХОД: НА ВЫХОДЕ ТЕРМИНАЛА ОТОБРАЖАЕТСЯ ОШИБКА

В МОЕМ КОДЕ ВХОДНЫЕ ВХОДЫ ВНИМАЮТСЯ С ИСПОЛЬЗОВАНИЕМ СТРУКТУР, ЗАТЕМ ОНИ СОХРАНЯЮТСЯ В ДВОИЧНОМ ФАЙЛЕ, ШКОЛЬНАЯ ЗАПИСЬ ИМЕЕТ ОТДЕЛЬНЫЙ ФАЙЛ, И КАЖДЫЙ КЛАСС ИМЕЕТ ОТДЕЛЬНЫЙ ФАЙЛ.

НУЖНО УДАЛИТЬ ЭТУ ОШИБКУ И ИСПРАВИТЬ МОЙ КОД

en.wikipedia.org/wiki/…
Support Ukraine 19.07.2024 07:35

Пожалуйста, не КРИЧИТЕ на нас, это грубо.

Some programmer dude 19.07.2024 07:37

Что касается проблемы, вы обычно получаете что-то подобное, если пишете за пределами вашей динамически выделяемой памяти. Вам нужно убедиться, что вы никогда этого не сделаете.

Some programmer dude 19.07.2024 07:37

Также прочитайте stackoverflow.com/help/minimal-reproducible-example

Support Ukraine 19.07.2024 07:41

И общий совет, который поможет при отладке , а также поиске и устранении таких проблем: не пишите большие куски кода сразу. Вместо этого начните с пустой функции main. Сборка с включенным дополнительным предупреждением, рассматриваемым как ошибки. Протестируйте программу и код всеми возможными способами. Затем вы добавляете очень небольшой фрагмент кода, возможно, даже одну или две строки. Соберите и протестируйте, как раньше. И так далее... Таким образом, если есть проблема, ее гораздо проще найти и решить. Возможно, создав минимально воспроизводимый пример.

Some programmer dude 19.07.2024 07:41

Кажется, клавиша Caps Lock застряла. Возможно, вы захотите заменить клавиатуру, чтобы можно было вводить строчные буквы. Никто не хочет читать пост, написанный заглавными буквами.

Tom Karzes 19.07.2024 07:46

Да, и пока вы показываете нам много кода (на самом деле слишком много кода), вы забыли две важные части: файлы заголовков.

Some programmer dude 19.07.2024 07:49

Также, пожалуйста, не размещайте изображения текста. Публикуйте текст как правильно отформатированный текст. Вы можете отредактировать свой вопрос, чтобы улучшить его.

Jabberwocky 19.07.2024 10:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
8
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В функции 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);

 
}

Вызов malloc использует значение school->no_of_students[i]. Однако это значение устанавливается всего несколькими строками позже. В момент использования он пока не имеет никакой ценности.

Как упоминалось в другом ответе, вы используете no_of_students в определенном классе, который еще не установлен. Почему бы вам не определить максимальный размер количества учеников в классе, а затем использовать no_of_students в качестве отслеживания людей, посещающих класс в настоящее время? Альтернативно, вы можете сохранить массив no_of_students в конце (и использовать fseek) или в начале. Сделав это, вы можете сначала загрузить необходимое количество студентов, прежде чем выполнять распределение.

Другие вопросы по теме

Похожие вопросы

Устраняет ли включение заголовка необходимость в внешних объявлениях?
Когда мне следует создать собственное расширение Postgres
Я пытаюсь создать систему входа в систему на языке C, которая скрывает пароль с помощью '*' при вводе и возвращается назад, когда пользователь вводит неверную информацию
Как заставить CMake находить системные библиотеки по умолчанию для связывания без ручных манипуляций со сценариями?
Печать целых чисел дважды в одном операторе printf в программе на языке C
Является ли оператор & важным для использования в качестве оператора адреса?
В языке C первый символ строковой переменной равен 0, но при печати 0 исчезает?
Язык программирования C Неопределенное поведение
Как я могу найти CRC по этим данным
Как/когда именно Cortex-M4 (STM32 F4) переключает свой R13 с MSP на PSP? Нужно ли вручную переключаться при использовании PSP во встроенном asm?