1

我在 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 作为全局变量并在程序结束时释放它,但我不禁觉得有更好的方法来做到这一点。如果使用得当,我不认为全局变量是邪恶的,但是我会很感激一些建议。

4

3 回答 3

4

为什么不只是在最后释放它?像这样的东西:

car *tofree;
car *ptr = head;
while(ptr) {
    tofree = ptr;
    ptr = ptr->next;
    free(tofree);
}
于 2013-09-08T07:23:33.197 回答
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);稍后在您的代码中编写。

确实,手动内存管理很痛苦,你需要避免内存泄漏。像valgrind这样的工具会很有帮助。您可以考虑改用Boehm 的垃圾收集器,因此请使用GC_MALLOCmalloc不用担心释放内存……阅读有关垃圾收集的更多信息。

于 2013-09-08T07:23:25.883 回答
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);
}
于 2013-09-08T09:05:42.427 回答