C 用单个存储元素清除动态链表会使程序崩溃

C 用单个存储元素清除动态链表会使程序崩溃,c,pointers,dynamic,linked-list,C,Pointers,Dynamic,Linked List,在我的学术作业中,我的任务是使用链表创建一个动态集合ADT。我的程序运行正常,但当我试图清除一个只有一个元素(因此,是单个节点)的集合时,我的程序崩溃了 以下是如何定义我的链接列表: typedef struct node{ int value; struct node *next; }Node; typedef struct List{ Node *head; Node *tail; }*SetList; 以下是相关功能: #include <s

在我的学术作业中,我的任务是使用链表创建一个动态集合ADT。我的程序运行正常,但当我试图清除一个只有一个元素(因此,是单个节点)的集合时,我的程序崩溃了

以下是如何定义我的链接列表:

typedef struct node{

    int value;
    struct node *next;

}Node;

typedef struct List{

    Node *head;
    Node *tail;
}*SetList;
以下是相关功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "List.h"

SetList ListCreate(){

    SetList lptr;
    lptr = malloc(sizeof(SetList));
    lptr->head = NULL;
    lptr->tail = NULL;
    return lptr;
}

SetList ListAdd(SetList lptr, int x){

    if(List_Is_Element_Of(x, lptr)){
            puts("Value already exists, enter a unique value");
    }
    else{
        Node *new = malloc(sizeof(Node));
        new->value = x;
        new->next = NULL;

        if(lptr->head == NULL){
            lptr->head = new;
            lptr->tail = new;
        }
        else{
            lptr->tail->next = new;
            lptr->tail = new;
        }
    }
        return lptr;
}


SetList ListRemove(SetList lptr, int x){

    if(lptr == NULL){
            puts("Memory Allocation Failed. Shutting down.");
            exit(EXIT_FAILURE);
    }
    else if(!List_Is_Element_Of(x, lptr)){
        puts("Value is not in set");
    }
    else if(lptr->head == NULL){
        puts("Set is empty. Cannot remove that which does not exist");
    }
    else{
        if(lptr->head->value == x){
        Node *tempnode = malloc(sizeof(Node));
        tempnode =  lptr->head;
        lptr->head = tempnode->next;
        free(tempnode);
        }
        else{
        Node *tempnode = malloc(sizeof(Node));
        tempnode =  lptr->head;
        Node *tempnode2 = malloc(sizeof(Node));
        tempnode2 = tempnode;
        while(tempnode->value != x){
            tempnode2 = tempnode;
            tempnode = tempnode->next;
        }
        tempnode2->next = tempnode->next;
        free(tempnode);
        }
    }
    return lptr;
}

SetList ListClear(SetList lptr){

    SetList templist = ListCreate();
    templist = lptr;
    while(templist->head!= NULL){
        ListRemove(templist, templist->head->value);
        templist->head = templist->head->next;
    }
    free(templist);
    return lptr;
}
#包括
#包括
#包括
#包括“List.h”
SetList ListCreate(){
集合列表lptr;
lptr=malloc(sizeof(SetList));
lptr->head=NULL;
lptr->tail=NULL;
返回lptr;
}
SetList ListAdd(SetList lptr,int x){
if(列表是(x,lptr)的元素){
puts(“值已存在,请输入唯一值”);
}
否则{
Node*new=malloc(sizeof(Node));
新建->值=x;
新建->下一步=空;
如果(lptr->head==NULL){
lptr->head=新建;
lptr->tail=new;
}
否则{
lptr->tail->next=新建;
lptr->tail=new;
}
}
返回lptr;
}
SetList ListRemove(SetList lptr,int x){
如果(lptr==NULL){
puts(“内存分配失败。正在关闭”);
退出(退出失败);
}
else如果(!List_是(x,lptr)的元素_){
看跌期权(“价值未设定”);
}
否则如果(lptr->head==NULL){
puts(“集合为空。无法删除不存在的集合”);
}
否则{
如果(lptr->head->value==x){
Node*tempnode=malloc(sizeof(Node));
tempnode=lptr->head;
lptr->head=tempnode->next;
自由(tempnode);
}
否则{
Node*tempnode=malloc(sizeof(Node));
tempnode=lptr->head;
Node*tempnode2=malloc(sizeof(Node));
tempnode2=tempnode;
while(tempnode->value!=x){
tempnode2=tempnode;
tempnode=tempnode->next;
}
tempnode2->next=tempnode->next;
自由(tempnode);
}
}
返回lptr;
}
设置列表清除(设置列表lptr){
SetList templist=ListCreate();
圣殿骑士=lptr;
while(圣堂武士->头!=NULL){
ListRemove(templist,templist->head->value);
圣堂武士->头=圣堂武士->头->下一步;
}
自由(圣殿骑士);
返回lptr;
}
我在指针方面不是很有经验,所以我不完全确定问题是从哪里来的。删除存储了单个元素的列表是可行的,但清除它却不行


提前感谢您的阅读。

您的清除功能不会改变Tail,尽管您似乎没有使用Tail(除了在添加节点时为其指定不同于head的节点?)

当clear删除最后一个元素时,head应该为null,因此在删除最后一个元素后取消对它的引用将是错误的


加上@NotLikeThat所说的。

如果我读对了:

SetList ListClear(SetList lptr){

    SetList templist = ListCreate();   // Create a new list
    templist = lptr;                   // Immediately throw away the new list
                                       //  by overwriting the pointer with the old one
    while(templist->head!= NULL){      // Delete everything from the old list
        ListRemove(templist, templist->head->value);
        templist->head = templist->head->next;
    }
    free(templist);                    // Free the old list
    return lptr;                       // Return a pointer to freed memory
}
如果要通过删除所有元素来清除列表,则不需要创建新的元素,只需在现有列表上迭代删除元素,直到其为空。该函数真正需要的就是
while
循环


我认为
ListRemove()
还应该检查它是否正在删除最后一个元素,并相应地更新
tail

sizeof(SetList)
是指针的大小,您需要
sizeof(struct List)
sizeof*lptr
;我发现您的代码中至少有三个内存泄漏,您丢弃了
malloc
的返回值。此外,你还返回了释放的指针。当涉及到内存泄漏时,我不太明白你在说什么,因为我的讲座不是特别好,我不得不在网上查找很多东西。你能详细说明吗?你说得对。因此,在您的评论之后,我决定循环while(lptr->head!=lptr->tail),然后在循环之后,我包括另一个ListRemove(lptr,lptr->head->value),以删除剩余的一个值,这似乎有效。