【问题标题】:Singly Linked List struct insert/delete multiple free单链表结构插入/删除多个空闲
【发布时间】:2011-04-23 04:49:16
【问题描述】:

看这段代码太久了,我越来越沮丧,任何自己弄清楚它的机会都已经失去了:(任何人都可以告诉我我在哪里愚蠢?我只是不明白我在哪里双重释放或者可能分配不正确(我必须这样做但是是的)。我不断收到 * glibc detected * free(): invalid next size

我实际上是在释放比我需要的更多的东西,还是我只是没有分配我需要分配的东西。 --sorry for bad indentation 无法让这个编辑器正确缩进

我有结构:

typedef int boolean;
typedef char * String;

typedef struct {
    char name[30];
    long ID;
    char address[40];
    char city[20];
    int age;
}Employee;

typedef struct node {
   Employee *anEmployee;
   struct node *next;
}NODE;

typedef struct {
   NODE *head, *tail;
}SLL;

插入函数--SLL(单链表)

void insert(SLL *list, Employee e){
  printf("insert");

   NODE *temp, *current;

   temp = (NODE *)malloc(sizeof(NODE));
   assert(temp != NULL);

   temp -> anEmployee = (Employee *)malloc(sizeof(Employee *));
   assert(temp -> anEmployee != NULL);

   strcpy(temp -> anEmployee -> name, e.name); 

   temp -> anEmployee -> ID = e.ID;

   strcpy(temp -> anEmployee -> address, e.address); 

   strcpy(temp -> anEmployee -> city, e.city);

   temp -> anEmployee -> age = e.age;

 if (list -> head == NULL) {     /* list is empty */
  list -> head = list -> tail = temp;
  return;
   }
   else { // list is not empty
       list -> tail -> next = temp;
       list -> tail = temp;
          }
 }

在删除函数中删除和释放内存

boolean delete(SLL *list, String str){
  printf("delete");
  NODE *temp, *temp2;
  if (list -> head == NULL) return FALSE;  // list is empty

temp = list -> head;

while ((temp != NULL) && (strcmp(temp -> anEmployee -> name , str) != 0))
   temp = temp -> next;

if (temp == NULL) return FALSE;  // str is not found in the list

// now temp points to the NODE with str in it.  Let us delete it
// from the list

    if ( list -> head == temp) { // temp points to the first NODE
       if (temp -> next == NULL) {  // temp points to the only NODE
           list -> head = list -> tail = NULL;
           free(temp -> anEmployee);
           free(temp);
           return TRUE;
     }
     // temp points to the first NODE but it is not the only NODE
     list -> head = temp -> next;
     free(temp -> anEmployee);
     free(temp);
     return TRUE;
  }

  if (temp -> next == NULL) {  // temp points to the last NODE
      temp = list -> head;
      temp2 = list -> head -> next;
      while(temp2 - > next != NULL){
        temp = temp->next;
        temp2 = temp2 ->next;
    }


       list -> tail = temp ;    
       list -> tail -> next = NULL;
       free(temp2 -> anEmployee);
       free(temp2);
       return TRUE;
  }
       // temp points to some NODE in the middle of the list
      temp2 = temp -> next;
 while(temp2 - > next != NULL){

    temp ->anEmployee = temp2 - > anEmployee // 
    temp = temp->next;
    temp2 = temp2 ->next;
}
    temp ->anEmployee = temp2 - > anEmployee

   list -> tail = temp ;    
   list -> tail -> next = NULL;
   free(temp2 -> anEmployee);
   free(temp2);
   return TRUE;
 }

【问题讨论】:

  • 对于缩进:用四个空格搜索并替换制表符。

标签: c struct malloc free


【解决方案1】:

首先,在insert,你正在分配

temp -> anEmployee = (Employee *)malloc(sizeof(Employee *));

它只分配足够的内存来保存Employee 指针,而不是整个Employee 结构。你应该为temp->anEmployee.分配一个sizeof(Employee)大小的块

只要您确实想释放 someNode->anEmployeesomeNode 以完全清理单个节点占用的内存,您对 free 的调用是有意义的。

您可以按如下方式简化您的 delete 实现:

boolean delete(SLL* list, String str)
{
    NODE* temp = list->head, *prev = NULL;
    while(temp != NULL && strcmp(temp->name, str) != 0) {
        prev = temp;
        temp = temp->next;
    }
    if(temp == NULL)
        return FALSE;

    if(prev != NULL)
        prev->next = temp->next;

    if(list->head == temp)
        list->head = temp->next;

    if(list->tail == temp)
        list->tail = temp->next;

    free(temp->anEmployee);
    free(temp);
    return TRUE;
}

通过跟踪查找之前的节点(如果有),您可以避免所有令人讨厌的特殊情况,并将核心列表更新减少到三个简单的条件分配。

【讨论】:

  • 我没有看到您要删除列表中间的节点的情况,但这确实大大简化了我的其余代码。 --nvm 我明白了。
【解决方案2】:

没有读完,delete 的第一行应该做什么?

  NODE *temp, *temp2; // temp is uninitialized

    if ( list -> head == temp) { // temp points to the first NODE

我不知道delete 应该删除什么。 str 参数似乎未使用。是否要根据str 搜索特定记录,设置temp 指向它,然后继续执行如图所示的代码?

【讨论】:

  • hhm 我删除了它通过列表搜索 str 的部分,如果发现它使 temp 指向该节点,则某些删除情况需要 temp2(应该可能使用开关)。
  • @Wilson:不要太争辩,但这种代码在 C++ 中同样高效且更容易编写。
  • @Wilson:同样不要太争论,但 Unix 只是一个操作系统家族,它们都可以很好地与 C++ 配合使用。这个问题显然是在应用程序编程领域。即使它是操作系统内核的一部分,也更有理由使用正确的工具来实现可靠性。 Mac OS X 是一流的 UNIX,在内核中使用 C++,在用户空间中使用 Objective-C——那又如何?
【解决方案3】:

在 insert() 中,当您分配 temp->anEmployee 时,您只是为指针分配了足够的空间,而不是完整的 Employee。

这一行:

   temp -> anEmployee = (Employee *)malloc(sizeof(Employee *));

应该是:

   temp -> anEmployee = (Employee *)malloc(sizeof(Employee));

【讨论】:

    猜你喜欢
    • 2020-09-05
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 2019-10-19
    • 2018-03-22
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多