2013-09-08 2 views
1

Я создал связанный список в C, который используется для хранения данных, которые затем изменяются по мере необходимости. При создании связанного списка я использовал следующиеСоздать фиксированный размер Связанный список в C

struct car_elements 
{ 
    char car_rego[7]; 
    double time_parked; 
    struct car_elements *next; 
}; 

typedef struct car_elements car; 

/* Defined as global variable to hold linked list */ 
car *head = NULL; 

car *SetupCars() 
{ 
    car *ptr = head; 
    car *new_car = NULL; 

    new_car = (car*) malloc(sizeof(car)); 
    if (!new_car) 
    { 
    printf("\nUnable to allocate memory!\n"); 
    exit(1); 
    } 

    strcpy(new_car->car_rego, "empty"); 
    new_car->time_parked = time(NULL); 
    new_car->next = NULL; 

    if (ptr == NULL) 
    { 
    return (new_car); 
    } 
    else 
    { 
    while (ptr->next) 
    { 
     ptr = ptr->next; 
    } 
    ptr->next = new_car; 
    return (head); 
    } 
} 

Из основного я называю следующее для создания связного списка

for(int i = 0; i<TOTAL_CARS; i++) { 
    head = SetupCars(head);  
} 

Проблема заключается в том, что теперь у меня есть утечка памяти - Есть ли лучше способ создания связанного списка с фиксированным размером. В конце выполнения программы я могу

free(head); 

Однако я не могу назвать в методе SetupCars

free(new_car); 

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

+2

Прежде всего - использование VALGRIND с: VALGRIND --leak-проверки = полная --track-истоках = да ... – mousomer

+3

Если вы хотите получить список с фиксированным размером почему бы не использовать массив? – Joni

ответ

1

Держите car *head глобальным var. Для SetupCars:

void SetupCars() /* void will do, unless you want a copy of the new "car" */ 
{ 
    car *new_car = NULL; 
    new_car = malloc(sizeof *new_car); /* don't need to cast return value of malloc */ 

    /* do checks and setup new_car... */ 

    if (head == NULL) /* first element */ 
    { 
    head = new_car; 
    } 
    else /* easier to add new_car as the FIRST element instead of last */ 
    { 
    new_car->next = head; 
    head = new_car; 
    } 
} 

С main создания связного списка точно так же:

for(int i = 0; i<TOTAL_CARS; i++) { 
    SetupCars(); /* without any arguments */ 
} 

Тогда в конце концов, вы цикл по списку и свободных объектов. Как Manoj Pandey писал в своем ответе:

car *tofree; 
car *ptr = head; 
while(ptr) { 
    tofree = ptr; 
    ptr = ptr->next; 
    free(tofree); 
} 
+1

Фантастический - проверен с valgrind и без утечек памяти. Все блоки кучи были освобождены - утечек не было. Мне еще многое предстоит узнать, но я очень ценю вашу помощь. Идеальное решение проблемы, которую я испытывал. – smuzoen

3

Вам нужна функция, чтобы освободить весь список, как:

void free_cars(car*p) { 
    while (p != NULL) { 
     car* nextp = p->next; 
     free (p); 
     p = nextp; 
    } 
} 

Таким образом, вы могли бы назвать

free_cars (head); 
head = NULL; 

возможно даже при наличии макро

#define DELETE_CARS(CarsVar) do { \ 
    free_cars(CarsVar); CarsVar = NULL; } while(0) 

затем просто написать DELETE_CARS(head); в вашем коде.

И действительно, руководство пользователя memory management является болезненным, вам необходимо избегать memory leaks. Инструменты, такие как valgrind, могут быть полезны. И вы могли бы вместо этого использовать Boehm's garbage collector, поэтому используйте GC_MALLOC вместо malloc и не беспокойтесь о том, чтобы освободить память .... Подробнее о garbage collection.

+0

Проверено с valgrind и без утечек памяти - вы, ребята, великолепны. Cheers – smuzoen

4

ПОЧЕМУ не просто освободить его в конце? SOhething вот так:

car *tofree; 
car *ptr = head; 
while(ptr) { 
    tofree = ptr; 
    ptr = ptr->next; 
    free(tofree); 
} 
Смежные вопросы