2014-09-25 4 views
0

Отказ от ответственности: Это мой первый вопрос о StackOverflow, и я новичок-программист, поэтому заблаговременно извиняюсь, если вы потрясены моим кодом или если я не опубликую свой вопрос надлежащим образом.(C) Не удается найти причину ошибки ядра с динамическим распределением

В любом случае, я работаю над учебным пособием с динамически распределенными структурами. Я разделил класс на три структуры: структуру студента (имя студента, идентификатор студента), структуру курса (название курса, идентификатор курса) и структуру регистрации (идентификатор студента, идентификатор курса, класс).

Проблема: Я могу ввести столько баллов, сколько мне нужно без ошибок для первого ученика. Когда я пытаюсь ввести оценку для второго студента, я сбрасываю базовый файл. Я проверил все переменные, чтобы увидеть, соответствуют ли они моей функции, и они есть. Ниже приведена моя структура Enroll и моя функция добавления класса.

typedef struct { 
    int Student_ID; 
    int Course_ID; 
    int *Grade; 
    int GradeCount; 
} Enroll_Database; 

Функция ...

void addGrade(Enroll_Database *Enroll) 
{ 
    int i = 0, j = 0, b, Course_Num, Student_Num, Grade; 

    printf("Enter Course Number: "); 
    scanf("%d", &Course_Num); 
    printf("Enter Student ID: "); 
    scanf("%d", &Student_Num); 

    /* For loop that traverses through the Enroll array until until it encounters 
     nothing in the Course ID */ 
    for(i = 0; Enroll[i].Course_ID != 0; i++) 
    { 

      /* if the Student Number and the Course Number are equal to their 
        appropriate Enroll element, then ask user to input Grade */ 
      if(Enroll[i].Student_ID == Student_Num && Enroll[i].Course_ID == Course_Num) 
      { 
        printf("Enter Grade: "); 
        scanf("%d", &Grade); 

        if(Enroll[i].GradeCount == 0) 
        { 
          Enroll->Grade = (int *) malloc(sizeof(int)); 
          Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps 
          Enroll[i].GradeCount++; 

        } 
        else 
        { 
          Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int)); 
          Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps 
          Enroll[i].GradeCount++; 
        } 

      } 
     } 
} 

Я провел несколько проверок и дамп происходит после того, как я таНос/перераспределить и назначить пользовательский ввод к значению класса в структуре ПРИЕМА.

Я был бы очень признателен за любую помощь, и я сожалею об этом, если мой код не читается или я отформатирован неправильно. Спасибо!

ответ

1

Это выделяет пространство для одного элемента. а также он перераспределяет неправильный указатель:

Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int)); 

Это может быть фиксированной, как это:

Enroll[i].Grade = realloc(Enroll[i].Grade, sizeof(int) * (Enroll[i].GradeCount + 1)); 

Запоминание, что X->Y, (*X).Y и X[0].Y все это означает то же самое: ваша оригинальная версия на самом деле перераспределена Enroll[0].Grade, вместо Enroll[i].Grade.


(Остальная часть этого ответа есть несколько возможных предложений по улучшению стиля :)

Чтобы избежать такого рода ошибок, я бы лично писать только после того, как scanf:

Enroll_Database *found = &Enroll[i]; 

и затем используйте found-> везде, а не Enroll[i].. В качестве альтернативы я бы подумал о том, чтобы иметь отдельную функцию, чтобы фактически добавить оценку (которая вызывается после того, как была найдена запись в базе данных).

Теперь, если вы инициализируете Enroll[i].Grade до NULL при настройке базы данных, вам действительно не понадобится это заявление if...else. Так как поведение realloc(NULL, X) совпадает с положением malloc(X), тот же код будет обрабатывать обе ситуации.

Обратите внимание, что в C вы should not cast the value returned by malloc и друзья.

Еще одна вещь, о которой нужно помнить, заключается в том, что стиль X = realloc(X, ... не позволяет вам восстанавливаться после отказа от распределения.Чтобы написать надежный код, вам необходимо предпринять некоторые разумные действия, когда функция malloc -family возвращает NULL; это может быть так же просто, как распечатать сообщение и вызвать exit.

+1

У меня есть это, чтобы работать без проблем. Спасибо! Я рассмотрю настройку своего кода на ваши рекомендации. – stancharoen

Смежные вопросы