如何在链接列表的c代码中修复此错误?

时间:2018-02-25 14:57:37

标签: c linked-list

我在Xcode上收到一个错误,当我在c中的单个链表的删除功能时,我不知道为什么。我收到的错误是 “malloc: *对象0x7ffeefbff5d8的错误:未释放指针被释放* 在malloc_error_break中设置断点以进行调试”

int delete (node ** list, int delete)
{
    node * current= *list;//declares current
    //stop at node that is one before i will need to delete (in this case iam deleting the 2node)
    if (*list != NULL)
    {
        node * temp= *list;
        temp = temp->next;
        free(list);
        *list=temp;

    }
    while (current->next->data != delete)
    {
        current=current->next;
    }
    node * temp;//Declares temp
    temp=current->next->next;
    free(current->next);//one after current free'd
    current->next=temp;
    return 0;
}

3 个答案:

答案 0 :(得分:0)

有许多事情不明确或不必要

  • 为什么要释放free(list); list是双指针,如果释放此headpointer链表将会松动。删除操作后如果需要,如何再次print/access列表?
  • list是持有链接的headpointer,您没有在main()或调用函数中为列表分配任何内存,因此您无法释放它。这就是为什么错误
  

释放的指针未分配

如果您想free,那么首先应该free(*list),然后free(list)

  • 来自您的代码段

    free(list); /* list is freed here */
    *list=temp; /* How will you access again *list */
    

根据我的想法,您的if区块应为

if (*list != NULL) {
    node * temp= *list;
    temp = temp->next; /* temp holds 2nd node address & you need that only */

}

答案 1 :(得分:0)

首先,您的问题非常清楚,下次请发布所有必要的代码,并在几行中解释该功能的目的。

我想您要做的是根据参数data的值从链接列表中删除特定项目。

来自网站learn-c

" 删除特定项目 要从列表中删除特定项目,无论是通过列表开头的索引还是通过其值,我们都需要检查所有项目,不断向前看,看看我们之前是否已经到达节点我们希望删除的项目。这是因为我们需要将位置更改为上一个节点指向的位置。

以下是算法:

  1. 在我们要删除的节点之前迭代到节点
  2. 将我们要删除的节点保存在临时指针
  3. 将上一个节点的下一个指针设置为指向我们要删除的节点后的节点
  4. 使用临时指针删除节点
  5. 我们需要处理一些边缘情况,因此请确保您了解代码。 " 然后他们发布了代码,我想你应该去那里看完整篇文章。

    祝你好运

答案 2 :(得分:0)

您的代码有错误的逻辑加上明显的错误。 一旦列表被释放,您无权再次访问它。

free(list);
*list=temp;

管理链接列表并不困难,但需要注意细节。

  • 当您删除列表中的节点时,您有责任连接节点。

  • 如果删除头部,则有责任移动头部。

  • 如果head是您要查找的节点,这是列表中唯一比删除后节点必须标记为NULL的节点。

下面的测试程序使用struct node *find(struct node *start, int data)函数查找符合条件的节点,并使用delete删除它。所有边缘案件都已得到妥善处理。

#include <stdio.h>
#include <stdlib.h>

// Basic simple single list implementation to illustrate 
// a proper deletion of the node which has a specfic data value.

// Node in List
typedef struct node {
    int data;
    struct node* next; // pointer to next node
}node;

// List structure
typedef struct list {
    node* head;     // The entry point into a linked list.  If the list is empty then the head is a null reference. 
} list;

// Create list
list* list_create()
{
    list* new_list = malloc(sizeof(list));

    if(new_list == NULL)
        return NULL;        // protection

    new_list->head = NULL;  // If the list is empty then the head is a null reference.  no elements in the list 

    return new_list;        // return created new list
}

// returns newly created node
node* node_new(int data)
{
    node* new_node = malloc(sizeof(node)); // allocate memory for the node 

    if (new_node == NULL)
        return NULL;                             // protection 

    new_node->data = data;                       // remember the data 
    new_node->next = NULL;                       // no next node

    return new_node;                             // return new created node
}

// The method creates a node and prepends it at the beginning of the list.
// 
// Frequently used names for this method:
// 
// insert at head
// add first
// prepend
//
// returns new head or NULL on failer

node* prepend_node(list* in_list, node* new_node)

{
   // Add item to the front of the in_list, return pointer to the prepended node (head)    

    if(in_list == NULL)
        return NULL;

    if(new_node == NULL)                         // problem, not enough memory
       return NULL;                              // in_list->head has not changed 

/* 
                 new_node      
                   |*| -->  NULL   
                   next        
*/       
    if(in_list->head == NULL)                    // if list is empty 
    {
        in_list->head = new_node;                // the new_node becomes a head   
    }
    else // list already have a head node
    {
/*
                |2|-->|1|-->NULL
                 ^ 
                 |
                 *
                head (2) (list pointer)

*/
        new_node->next = in_list->head;     // now, the new node next pointer points to the node pointed by the list head, see below:       

/* 
          new_node     
            |3|-->     |2|-->|1|-->NULL
                        ^  
                        |
                        *
                       head (list pointer)
*/          
        in_list->head = new_node;               // the list head has to move to new_node ( a new prepanded node)  

 /* 
          new_node       
            |3|-->  |2|-->|1|-->NULL
             ^       
             |           
             *           
            head (3) (list pointer)
*/         
    }

    return in_list->head;                       // we are returning pinter to new_node
}

// Print out list
void print_list(list* in_list)
{
    node* node;

    if (in_list == NULL)
    {
        return;
    }

    if (in_list->head == NULL)
    {
        printf("List is empty!\n");
        return;
    }

   printf("List: ");

   node = in_list->head;

    while(node != NULL)
    {
        printf(" %d", node->data);

        node = node->next;
    }

    printf("\n");
}

struct node *find(struct node *start, int data)             // find p to be removed
{
    node* node;

    if (start == NULL)
        return NULL;

    node = start;

    while(node != NULL)
    {
        if (node->data == data)
            return node; 

        node = node->next;
    }

    return NULL;
}


int delete(struct node **start, int data)
{
     struct node *p, *prev, *next, *to_free;

     if (start == NULL)                      // protection
        return 0;

     p = find(*start, data);                 // find p to be removed

     if (p == NULL)
        return 0;

     if (*start == NULL)
        return 0;                            // protection

     if(*start == p)                         // head == p
     {
        if((*start)->next !=NULL)
        {
            *start = (*start)->next;         // remember next 
            free(p);
            printf("Head removed\n");
            return 1;
        }
        else // the only node
        {
            free(p);

            printf("Last node removed\n");
            *start = NULL;

            return 1;
        }
     }

     // p != start:

     next = *start; 

     while (next != NULL)
     {
        prev = next;                       
        to_free = next->next;                // candidate to be freed   

       if( to_free == p )
        {
            prev->next = to_free->next;      // connect nodes before deletion 

            free(to_free);                   // now free the remembered `next`
            to_free = NULL;                  // so it does not point to the released memory
            return 1;
        }

        next = next->next;                   // this node was not a match 
     } //while

    return 0; 
}

int main() {

   list* new_list = list_create();

   node *n1 = node_new(1);
   node *n2 = node_new(2);
   node *n3 = node_new(3);

  // list is empty
   print_list(new_list);

   prepend_node(new_list, n1);
   prepend_node(new_list, n2);
   prepend_node(new_list, n3);

  // list has 3 elements
   print_list(new_list);

   delete(&new_list->head, 3);  
   print_list(new_list);

   delete(&new_list->head, 1);  
   print_list(new_list);

   delete(&new_list->head, 2);
   // list has 2 elements
   print_list(new_list);

   printf("head: %p\n",new_list->head);

   print_list(new_list);

  free (new_list); // after deleting all elements, delete the list itself
  return 0;
}

输出:

List is empty!
List:  3 2 1
Head removed
List:  2 1
List:  2
Last node removed
List is empty!
head: (nil)
List is empty!