在C中创建固定大小的链接列表

时间:2013-09-08 07:19:20

标签: c singly-linked-list

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

从main我调用以下内容来创建链表

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

问题是现在我有内存泄漏 - 是否有更好的方法来创建固定大小的链表。在程序运行结束时我可以

free(head);

但是我无法在SetupCars方法中调用

free(new_car); 

我可以创建new_car作为一个全局变量我想在程序结束时释放它但我不禁觉得有更好的方法来做到这一点。如果使用得当,我不认为全局变量是邪恶的,但我会感激一些建议。

3 个答案:

答案 0 :(得分:4)

为什么不只是在最后释放它?这样的事情:

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

答案 1 :(得分: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 leaksvalgrind之类的工具可能会有所帮助。您可以考虑使用Boehm's garbage collector,因此请使用GC_MALLOC代替malloc而不要忘记释放内存....阅读有关garbage collection的更多信息。

答案 2 :(得分:1)

car *head保留为全局变量。对于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);
}