c-为什么memcheck报告内存泄漏(双链表)



处理简单的双链表。

struct list_node {
struct list_node *prev, *next;
int data;
};
struct list {
struct list_node *first, *last;
};

创建和推送如下:

struct list *list_create(void) {
struct list *_list = malloc(sizeof(struct list));
if(_list == NULL) {
die("Memory allocation error for list_createn");
}
_list->first = NULL;
_list->last = NULL;
return _list;
}
void list_push(struct list *list, int item_data) {
struct list_node *_node = malloc(sizeof(struct list_node));
if(_node == NULL) {
die("Memory allocation error for list_pushn");
}
_node->prev = NULL;
_node->next = NULL;
_node->data = item_data;
//empty list case
if(list->last == NULL) {
list->first = _node;
list->last = _node;
}
else {
_node->prev = list->last;
list->last->next = _node;
list->last = _node;
}
}

一次推送有效,但连续两次推送会导致节点大小的内存泄漏
我这里缺少什么?

为了完成,这里是我的列表free,我在代码中称之为:

void list_destroy(struct list *list) {
if (list->first != NULL) {
struct list_node *p = list->first;
//if one node list
if(list->first == list->last) {
list->first = NULL;
list->last = NULL;
free(p);
p = NULL;
}
else {
while (p->next) {
struct list_node *q = p;
p = p->next;
free(q);
q = NULL;
}
}
}
free(list);
}

[SOLVED]Bug在list_destroy中-上次通过while(p->next)导致最后一个p节点未正确处理。谢谢大家!

内存泄漏是由while循环中的函数list_destroy产生的

while (p->next) {
struct list_node *q = p;
p = p->next;
free(q);
q = NULL;
}

由于while循环的条件,列表的最后一个节点没有释放

while (p->next) {

因为对于最后一个节点,数据成员CCD_ 6等于CCD_。

把功能分成两部分是没有意义的。的功能如下

void list_destroy(struct list *list) {
while ( list->first )
{
struct list_node *p = list->first;
list->first = list->first->next;
free( p );
}
free( list );
}   

最好是通过引用通过指向它的指针来传递指针列表,例如

void list_destroy(struct list **list) {
struct list_node *current = ( *list )->first;
while ( current )
{
struct list_node *p = current;
current = current->next;
free( p );
}
free( *list );
*list = NULL;
}   

在这种情况下,函数执行后,调用方中指向列表的指针将等于NULL。

您也可以编写一个函数来清除列表。的外观如下

void list_clear(struct list *list) {
while ( list->first )
{
struct list_node *p = list->first;
list->first = list->first->next;
free( p );
}
list->last = NULL;
}   

来自莫斯科的弗拉德写了一个更干净的版本。我想加上";防御性编程";。假设create()push()destroy()之前被调用是危险的。事实上,您可以避免一个很难找到的错误(在调用代码中使用指针,在它被释放后(((始终检查"传入"参数。

在呼叫代码中:

myList = list_destroy( myList );

并返回一些可以使用的东西。

list_t *list_destroy( list_t *pList ) {
assert( pList != NULL );
// iterate releasing alloc'd blocks...
return NULL;
}

最新更新