c中的可用内存问题删除了链表中的某些值

c中的可用内存问题删除了链表中的某些值,c,data-structures,linked-list,C,Data Structures,Linked List,我有一个问题是如何释放链表中已删除节点的内存。上面的函数,node是我想要操作的链表,int是我想要删除的值。谢谢大家! 它目前正在导致valgrind错误,我不知道从哪里开始。我试过免费(n,p),但这没有帮助 typedef struct node_t { int val; struct node_t *next; } node; node *deleteNumber(node *node, int i) { while (node && node->v

我有一个问题是如何释放链表中已删除节点的内存。上面的函数,
node
是我想要操作的链表,
int
是我想要删除的值。谢谢大家!

它目前正在导致valgrind错误,我不知道从哪里开始。我试过免费(n,p),但这没有帮助

typedef struct node_t { int val; struct node_t *next; } node;   

node *deleteNumber(node *node, int i) {
    while (node && node->val == i) {
        node = node->next;
    }
    n = node;
    p = node;
    if (n == NULL)
        return NULL;
    n = n->next;
    while (n) {
        if (n->val == i)
            p->next = n->next;
        else
            p = p->next;
        n = n->next;
    }
    return node;
}

我不完全确定您的
deleteNumber
应该做什么,但是下面的版本释放列表中与该数字匹配的所有元素,返回指向剩余列表的第一个元素的指针(如果列表现在为空,则返回
NULL

#包括
typedef结构节点{int val;结构节点{u t*next;}节点;
节点*删除编号(节点*开始,int i){
节点*n=开始;
node*p=NULL;
节点*t;
while(n){
t=n;
n=n->next;
如果(t->val==i){
如果(p)
p->next=n;
其他的
开始=n;
自由(t);
}否则{
p=t;
}
}
返回启动;
}
以下是一些用于测试上述功能的附加功能:

#include <stdlib.h>

typedef struct node_t {   int val;   struct node_t *next; } node;

node* deleteNumber(node* start, int i) {
    node* n = start;
    node* p = NULL;
    node* t;

    while (n) {
        t = n;
        n = n->next;
        if (t->val == i) {
            if (p)
                p->next = n;
            else
                start = n;
            free(t);
        } else {
            p = t;
        }
    }
    return start;
}
#包括
/*将编号追加到列表,返回列表的开头*/
节点*地址编号(节点*开始,int i){
节点*t;
t=malloc(sizeof(*t));
如果(t==NULL)
返回启动;
t->next=NULL;
t->val=i;
如果(启动){
节点*p=开始;
while(p->next)
p=p->next;
p->next=t;
}否则{
开始=t;
}
返回启动;
}
/*打印列表的元素*/
无效打印列表(节点*列表){
while(列表){
printf(“%d”,列表->值);
列表=列表->下一步;
}
}
/*免费完整列表*/
无效删除列表(节点*列表){
节点*t;
while(列表){
t=列表;
列表=列表->下一步;
自由(t);
}
}
内部主(空){
const int test[]={2,3,4,2,5};
node*start=NULL;
int i;
/*构建一个列表*/
对于(i=0;i

上述代码中不应存在任何Valgrind错误。

为了
释放从列表中删除的节点,必须先保存
下一个
成员,然后才能释放节点,因为一旦节点被释放,就无法访问它

以下是修改后的版本:

#include <stdio.h>

/* append number to list, returning start of list */
node* addNumber(node* start, int i) {
    node* t;

    t = malloc(sizeof(*t));
    if (t == NULL)
        return start;
    t->next = NULL;
    t->val = i;
    if (start) {
        node* p = start;

        while (p->next)
            p = p->next;
        p->next = t;
    } else {
        start = t;
    }
    return start;
}

/* print elements of list */
void printList(node* list) {
    while (list) {
        printf(" %d", list->val);
        list = list->next;
    }
}

/* free whole list */
void deleteList(node* list) {
    node* t;

    while (list) {
        t = list;
        list = list->next;
        free(t);
    }
}

int main(void) {
    const int test[] = { 2, 3, 4, 2, 5 };
    node* start = NULL;
    int i;

    /* construct a list */
    for (i = 0; i < sizeof(test) / sizeof(test[0]); i++)
        start = addNumber(start, test[i]);
    /* report initial list contents */
    printf("Before:");
    printList(start);
    printf("\n");
    /* delete a number from the list */
    start = deleteNumber(start, 2);
    /* report updated list contents */
    printf("After:");
    printList(start);
    printf("\n");
    /* delete remaining elements of the list to appease Valgrind */
    deleteList(start);
    return 0;
}
为了避免代码重复,您可以使用更高级的双指针方法:

typedef struct node_t { int val; struct node_t *next; } node;   

node *deleteNumber(node *node, int i) {
    node *next, *n, *p;
    while (node && node->val == i) {
        next = node->next;
        free(node);
        node = next;
    }
    if (node != NULL) {
        p = n = node;
        n = n->next;
        while (n) {
            if (n->val == i) {
                next = p->next = n->next;
                free(n);
                n = next;
            } else {
                p = n;
                n = n->next;
            }
        }
    }
    return node;
}

当你谈论错误时,请,请,让我们看看你谈论的错误。我们看不到您的计算机。当您删除一个节点时,返回一个未更改的
节点
:假设您删除了第一个节点?但是当您到达列表的末尾时,
返回NULL
。错误是在以后发生的吗?
deleteNumber
的预期行为是什么?实际的行为看起来很奇怪。看起来它正在尝试从列表中删除所有节点,其中
->val==i
,但这并不是它真正要做的。更新的问题例如,链接列表是l1=2,2,3,4,5,我输入deleteNumber(l1,2),它的结果应该是3,4,5@codingmonkeylol对于
l2
=2,3,3,2,5和
deleteNumber,它应该做什么(l2,2)
?返回3,3,5,但仍存在内存泄漏问题==1650==Memcheck,内存错误检测器==1650==Copyright(C)2002-2015,GNU GPL'd,由Julian Seward et al.==1650==使用Valgrind-3.11.0和LibVEX;使用-h重新运行版权信息==1650==命令:./delete==1650====1650==堆摘要==1650==在出口处使用:5个块中的80字节==1650==堆总使用量:12个allocs,7个frees,192个字节分配==1650==泄漏摘要:==1650==绝对丢失:3个块中有48个字节==1650==间接丢失:2个块中有32个字节blocks@codingmonkeylol在退出程序之前,您是否释放列表中的剩余元素?它说它已丢失3个块,并且在您调用deleteNumber之后,列表中还有三个元素。巧合?
typedef struct node_t { int val; struct node_t *next; } node;   

node *deleteNumber(node *node, int i) {
    node *next, *n, *p;
    while (node && node->val == i) {
        next = node->next;
        free(node);
        node = next;
    }
    if (node != NULL) {
        p = n = node;
        n = n->next;
        while (n) {
            if (n->val == i) {
                next = p->next = n->next;
                free(n);
                n = next;
            } else {
                p = n;
                n = n->next;
            }
        }
    }
    return node;
}
typedef struct node_t { int val; struct node_t *next; } node;   

node *deleteNumber(node *node, int i) {
    node **np = &node;

    while (*np) {
        node *n = *np;
        if (n->val == i) {
            *np = n->next;
            free(n);
        } else {
            np = &n->next;
        }
    }
    return node;
}