2016-03-31 3 views
-1

Вот некоторые вложенные структуры:Как освободить динамически распределенный вложенный массив структуры в C?

struct bat 
{ 
    int match,run,fifty,best; 
    double average,strike_rate; 
}; 
struct ball 
{ 
    char *best; 
    int match,wicket,fiveW; 
    double economy,average; 
}; 
struct Player 
{ 
    char *name; 
    char *country; 
    char *role; 
    struct bat *batting; 
    struct ball *bowling; 

}; 
struct Team 
{ 
    char *name; 
    char *owner; 
    char *rank; 
    char *worth; 
    char *match; 
    char *won; 
    char *lost; 
    struct Player *plist; 
} *team; 

Ниже я динамически распределяемой массив 7 struct Team типа, используя указатель *team каждый из которых содержит 16 struct Player массива типа с использованием *plist. struct Player имеет также две вложенные структуры.

int i,j; 
    team=(struct Team *) calloc(7,sizeof(struct Team)); 
    for(i=0; i<7; i++) 
    { 
     (team+i)->name=(char*) malloc(1*100); 
     (team+i)->owner=(char*) malloc(1*100); 
     (team+i)->rank=(char*) malloc(1*100); 
     (team+i)->worth=(char*) malloc(1*100); 
     (team+i)->match=(char*) malloc(1*100); 
     (team+i)->won=(char*) malloc(1*100); 
     (team+i)->lost=(char*) malloc(1*100); 
     (team+i)->plist=(struct Player *) calloc(16,sizeof(struct Player)); 
     for(j=0; j<16; j++) 
     { 
      (((team+i)->plist)+j)->name=(char*) malloc(1*100); 
      (((team+i)->plist)+j)->country=(char*) malloc(1*100); 
      (((team+i)->plist)+j)->role=(char*) malloc(1*100); 
      (((team+i)->plist)+j)->batting=(struct bat *) malloc(sizeof(struct bat)); 
      (((team+i)->plist)+j)->bowling=(struct ball *) malloc(sizeof(struct ball)); 
      ((((team+i)->plist)+j)->bowling)->best=(char*) malloc(1*100); 
     } 
    } 

Теперь я присвоил значения всем этим и выполнил некоторые задачи. Пришло время освободить всех этих dynamically allocated arrays. Каков правильный способ освободить все выделенное выше?

Я попытался освободиться, как показано ниже, но программа извлекает run-time error и аварий:

for(i=0; i<7; i++) 
    { 
     free((team+i)->name); 
     free((team+i)->owner); 
     free((team+i)->rank); 
     free((team+i)->worth); 
     free((team+i)->match); 
     free((team+i)->won); 
     free((team+i)->lost); 
     for(j=0; j<16; j++) 
     { 
      free((((team+i)->plist)+j)->name); 
      free((((team+i)->plist)+j)->country); 
      free((((team+i)->plist)+j)->role); 
      free((((team+i)->plist)+j)->batting); 
      free(((((team+i)->plist)+j)->bowling)->best); 
      free((((team+i)->plist)+j)->bowling); 
     } 
     free(((team+i)->plist)); 
    } 
    free(team); 

Как освободить всех тех, кто dynamically allocated memory правильно?

+2

Бесплатно каждый указатель вы 'malloc()' ated, в обратном порядке выделения. –

+3

OT: Не бросать 'malloc', а' sizeof (char) 'всегда' 1' –

+0

Да, просто прочитайте в обратном порядке (и подумайте о переходе на C++). –

ответ

3

Я положил некоторые ноты первые, некоторые из них из комментариев:

  • Не отвергни результат malloc/calloc. Это может скрыть ошибки/предупреждения, если вы забудете включить stdlib.h.
  • sizeof(char) является 1. Всегда.
  • Использование calloc, когда более поздняя инициализация всей выделенной памяти является нонсенсом: используйте только malloc.
  • ((((team+q)->plist)+b)->bowling)->best является уродливым читать. Лучше использовать обозначение массива:

    team[q]->plist[b]->bowling->best 
    

    Хотя он не покупает много с точки зрения удобочитаемости здесь, ИМО.

  • q и b являются не осмысленные имена переменных.

  • Если ваши строки имеют фиксированную длину, то почему вы вообще не используете динамическое распределение? Просто используйте элементы массива с фиксированной длиной, например char name[100]. То же самое касается plist: Если вы знаете, то это будет 16 игроков, а затем просто сделайте массив с постоянным размером.

Тогда у вас должны быть как функции построения, так и уничтожения для каждой вашей структуры, имитирующие конструкторы и деструкторы с объектно-ориентированных языков (поскольку вы программируете в почти объектно-ориентированном стиле). Так считает написание функций

void construct_team(struct Team * team) { 
    // allocating any members, calling construct_* of structure members 
} 
void destruct_team(struct Team * team) { 
    // free any members, calling destruct_* of structure members, in 
    // the exact reversed order as in the construct function! 
} 

Таким образом, вы бы заметили, что у вас нет «соответствий распределения» для

free((team+q)); // Never allocated team+q (the individual array elements), just the whole array team! 

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

+0

Такой подробный и полезный ответ - все же не принят как ответ и только 2 голоса (один из них от меня). Иногда Stackoverflow странно. – Gewure

2

Эти строки неправильны:

 free(((team+q)->plist)+q); 
     free((team+q)); 
    } 

Они должны быть:

 free((team+q)->plist); 
    } 
free(team); 

ПРИМЕЧАНИЕ: Я думаю, @ ошибка Tavij является думать, что каждый элемент массива в calloc эд должен быть free d индивидуально, что, конечно, неверно.

+0

Обратите внимание, что этот код выполняется внутри цикла, а 'team' - массив, вы не можете опустить' + q'. –

+0

@AlterMann Моя первоначальная версия имела неправильный отступ. Я исправил это, так что, возможно, теперь это имеет больше смысла. Окончательный 'free (team);' находится после цикла 'for'. –

+0

Ой, ты прав! –

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

  • Нет связанных вопросов^_^