C通过参考删除链接列表?

时间:2021-04-17 07:21:13

Brand new to C, tried other SO Answers that I found about this before posting, and saw that none of them were using a function and passing their list in by reference for deleting all item, but that is the way I want to implement it. Console is outputting

C的全新,在发布之前尝试了我发现的其他SO Answers,并且看到他们都没有使用函数并通过引用传递他们的列表来删除所有项目,但这是我想要实现它的方式。控制台正在输出

* Error in `./testing': double free or corruption (out): 0x00007ffc26622b30 * Aborted

* ./testing'出错:double free或corruption(out):0x00007ffc26622b30 * Aborted

Awesome error message for a noob! That isn't cryptic at all. :)
P.S. All of my other functions are working as intended.

noob的真棒错误信息!这根本不是神秘的。 :) P.S.我的所有其他功能都按预期工作。

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

typedef struct node
{
    int n;
    struct node* next;
} 
node;

bool search(int number, node* list);
void showItems(node* list);
void insertItem(int number, node** list);
void deleteItem(int number, node** list);
void deleteList(node** list);

int main(void)
{

    node* list = NULL;

    insertItem(1337, &list);
    insertItem(1337, &list);

    bool found = search(5, list);
    if (found)
    {
        printf("found number in linked list.");
    }

    deleteList(&list);

    showItems(list);
}

void showItems(node* list)
{
    node* ptr = list;
    while (ptr)
    {
        printf("%i\n",ptr->n);
        ptr = ptr->next;
    }
}

bool search(int number, node* list)
{
    node* ptr = list;
    while (ptr)
    {
        if (ptr->n == number)
        {
            return true;
        }
        ptr = ptr->next;

    }
    //Number not found.
    return false;
}

void insertItem(int number, node** list)
{
    node* newItem = malloc(sizeof(node));
    newItem->n = number;
    newItem->next = *list;
    *list = newItem;
}

void deleteItem(int number, node** list)
{

    node* ptr = *list;
    node* prev = NULL;

    while (ptr)
    {
        if (ptr->n == number)
        {
            if (prev != NULL)
            {
                //Check if there is a previous node.  If there is, set its next node to the current items next node.  Then free the current node.
                prev->next = ptr->next;

            }
            free(ptr);
            break;
        }
        prev = ptr;
        ptr = ptr->next;
    }
}

void deleteList(node** list)
{
    node* temp = NULL;
    while (list)
    {
        temp = *list;
        free(list);
        list = &temp->next;
    }
}

2 个解决方案

#1


4  

A better solution would look something like this:

一个更好的解决方案看起来像这样:

while(*list) {
  node* tmp = (*list)->next;
  free(*list);
  *list = tmp;
}

Your solution stores the address of the node pointed to by list, then frees what you never alloc'd - you attempt to free a node**, but you only alloc nodes. After doing that, you then try to dereference the memory that you just (sorta) tried to free.

您的解决方案存储列表指向的节点的地址,然后释放您从未分配的内容 - 您尝试释放节点**,但您只分配节点。在这之后,您尝试取消引用您刚刚(sorta)试图释放的内存。

You need to store a pointer to the next node, free the current node, and then move onto the next node.

您需要存储指向下一个节点的指针,释放当前节点,然后移动到下一个节点。

#2


1  

For a noob, this is good coding. But I have seen some flaw.

对于菜鸟来说,这是一个很好的编码。但我看到了一些缺陷。

First, in function "deleteItem" you check if (prev != NULL) but you do nothing when it's NULL. You have to update *list.

首先,在函数“deleteItem”中检查是否(prev!= NULL)但是当它为NULL时你什么都不做。你必须更新*列表。

    if (prev != NULL)
    {
        //Check if there is a previous node.  If there is, set its next node to the current items next node.  Then free the current node.
        prev->next = ptr->next;
    } 
    else // you have to add an else here
    {
        *list = ptr->next;
    }

Then, in the function "deleteList", I see three misteakes.

然后,在函数“deleteList”中,我看到三个misteakes。

  • you test list, but "list" is a pointer on a pointer. The pointer is "*list"
  • 你测试列表,但“列表”是指针上的指针。指针是“* list”
  • you use the memory after you called free()
  • 你调用free()后使用内存
  • you free list, but here again the pointer is "*list"

    你*列表,但这里再次指针是“*列表”

    node* temp = NULL;
    while (list)
    {
        temp = *list;
        free(list);
        list = &temp->next;
    }
    

You can write something like:

你可以这样写:

    while (*list)
    {
        node *temp = (*list)->next;
        free(*list);
        *list = temp;
    }

#1


4  

A better solution would look something like this:

一个更好的解决方案看起来像这样:

while(*list) {
  node* tmp = (*list)->next;
  free(*list);
  *list = tmp;
}

Your solution stores the address of the node pointed to by list, then frees what you never alloc'd - you attempt to free a node**, but you only alloc nodes. After doing that, you then try to dereference the memory that you just (sorta) tried to free.

您的解决方案存储列表指向的节点的地址,然后释放您从未分配的内容 - 您尝试释放节点**,但您只分配节点。在这之后,您尝试取消引用您刚刚(sorta)试图释放的内存。

You need to store a pointer to the next node, free the current node, and then move onto the next node.

您需要存储指向下一个节点的指针,释放当前节点,然后移动到下一个节点。

#2


1  

For a noob, this is good coding. But I have seen some flaw.

对于菜鸟来说,这是一个很好的编码。但我看到了一些缺陷。

First, in function "deleteItem" you check if (prev != NULL) but you do nothing when it's NULL. You have to update *list.

首先,在函数“deleteItem”中检查是否(prev!= NULL)但是当它为NULL时你什么都不做。你必须更新*列表。

    if (prev != NULL)
    {
        //Check if there is a previous node.  If there is, set its next node to the current items next node.  Then free the current node.
        prev->next = ptr->next;
    } 
    else // you have to add an else here
    {
        *list = ptr->next;
    }

Then, in the function "deleteList", I see three misteakes.

然后,在函数“deleteList”中,我看到三个misteakes。

  • you test list, but "list" is a pointer on a pointer. The pointer is "*list"
  • 你测试列表,但“列表”是指针上的指针。指针是“* list”
  • you use the memory after you called free()
  • 你调用free()后使用内存
  • you free list, but here again the pointer is "*list"

    你*列表,但这里再次指针是“*列表”

    node* temp = NULL;
    while (list)
    {
        temp = *list;
        free(list);
        list = &temp->next;
    }
    

You can write something like:

你可以这样写:

    while (*list)
    {
        node *temp = (*list)->next;
        free(*list);
        *list = temp;
    }