Я правильно использую malloc? - PullRequest
3 голосов
/ 03 декабря 2010

Добрый день!

Мне нужно использовать malloc при создании системы списков студентов .... Чтобы быть эффективными, наш профессор попросил нас использовать его в структуре, поэтому я создал структуру следующим образом:

struct student {
       char studentID[6];
       char name[31];
       char course [6];
};
struct student *array[30];

каждый раз, когда я добавляю запись, то есть когда я использую malloc ...

array[recordCtr]=(struct student*)malloc(sizeof(struct student));
recordCtr++;

тогда я освобождаю это так.

 for(i = 0; i < recordCtr; i++){
       free(array[i]);
  } 

Правильно ли я использую malloc ??? Каков эффект, если я освобождаю его так, как показано в цикле выше?

free(array);

Заранее спасибо. Ваше мнение будет высоко оценено.

Ответы [ 10 ]

4 голосов
/ 03 декабря 2010

У тебя все хорошо.

free(array); было бы неопределенным поведением, потому что array само не было выделено через malloc, поэтому вы не можете free это и не нужно - память будет управляться компилятором.

3 голосов
/ 03 декабря 2010

Хороший совет всегда делать:

type *something;
something = malloc(n * sizeof(*something));

Это потому, что если вы меняете тип чего-либо, вам не нужно менять все виды другого кода.И sizeof на самом деле является операцией компилятора, во время выполнения она не станет чем-то другим.

Кроме того, не приводите указатель void *, возвращаемый функцией malloc, в C нет причин делать это, и он просто еще больше связывает ваш код.сделать:

(struct student*)malloc(sizeof(struct student));

но

malloc(sizeof(**array));
2 голосов
/ 03 декабря 2010

Нет ничего противозаконного в том, как вы используете malloc, но это не список, а массив указателей.

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

Для навязчивого списка вы ставите struct student * next в декларации студента. Для неинтрузивного списка вы создаете другую структуру struct student_list_node, которая содержит экземпляр struct student и указатель struct student_list_node * next;

Это пример неинтрузивной версии:

struct student_list_node
{
  struct student data;
  struct student_list_node * next;
};

struct student_list_node * head;
struct student_list_node * tail;

struct student_list_node * addStudentToTail()
{
   struct student_list_node * newnode = (struct student_list_node *)(malloc( sizeof(struct student_list_node ) );
   /* check malloc did not fail or use a checking vesrion of malloc */
   if( !tail )
   {
      head = tail = newnode;
   }
   else
   {
      tail->next = newnode;
      tail = newnode;
   }
   return newnode; // which is also "tail"
}

int main()
{
   struct student_list_node * node = addStudentToTail();
   struct student * pstud = &node->data;
   /* write to pstud student details */
}

Если вы действительно хотите использовать массив, вы можете сделать его массивом студентов, а не студентов *, в этом случае вы можете использовать calloc вместо malloc

struct student * array = (struct student *)calloc( 30, sizeof( student ) );

Тогда использование free(array) будет правильным способом избавиться от него. У вас также есть возможность выделить больше, если вам это понадобится позже, с помощью realloc. (Будьте осторожны с этим: вы должны хранить копию своего исходного указателя, пока не узнаете, что realloc преуспевает).

1 голос
/ 03 декабря 2010

Есть простое правило: каждый malloc() должен быть связан с free() с указателем, возвращаемым malloc.Не меньше, не больше.

1 голос
/ 03 декабря 2010

Инициализируйте ваш массив указателей для структуры студентов со значениями NULL

for(i = 0; i < recordCtr; i++){
       array[i] = NULL;
  } 

Свободная память, если массив [i] не равен NULL

for(i = 0; i < recordCtr; i++){
       if(NULL != array[i])
       {
           free(array[i]);
       }
  } 
1 голос
/ 03 декабря 2010

То, что у вас будет, будет отлично работать.Как уже упоминали другие, вы создали массив указателей в стеке, и вам нужно malloc и освободить каждый из них по отдельности, как вы делаете.

Однако вам не нужно использовать malloc и freeЗа один раз, вы можете сделать что-то вроде этого:

int arraySize = 30;
student * ourArray = (student*)malloc(sizeof(student) * arraySize);

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

Надеюсь, что это поможет некоторым.

1 голос
/ 03 декабря 2010

выглядит хорошо.

Вы можете (если это соответствует вашей задаче) выделить место для всех 30 структур за один раз

 struct student *array = (struct student *)malloc(30*sizeof(struct student));

когда вы хотите избавиться от места, вы можете сделать

free(array)
1 голос
/ 03 декабря 2010

Да, вы используете его правильно. Есть лучшие способы организовать хранилище, чем это, но это будет работать. По крайней мере, пока вам не понадобится более 30 студентов ...

Обратите внимание, что вы должны вызывать free() с каждым указателем, который возвращается malloc(). Это означает, что ваш цикл по массиву указателей является правильным подходом для выбранной вами архитектуры.

Ваша попытка вызвать free для самого массива не будет работать. Он вызывает неопределенное поведение, потому что вы передаете указатель (на базу самого массива) на free(), который не пришел из вызова на malloc().

1 голос
/ 03 декабря 2010

То, что вы делаете, правильно.

Вы можете думать о *array[30] как о массиве из 30 указателей. Когда вы выделяете память для каждого из этих указателей, вам также нужно вызывать free () для каждого из них.

1 голос
/ 03 декабря 2010

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

Ваше текущее решение верное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...