我有一个简单的链表实现,包括push,pop,unshift和shift函数,可根据需要添加/删除数据 . 我想确保在通过调用pop和shift来检索数据时,我的实现不会泄漏内存 .
我如何释放已经通过malloc分配的内存,同时还将数据返回给调用者?
list.h
typedef struct _list_cell_t {
void *data;
struct _list_cell_t *next;
} list_cell_t;
typedef struct _list_cell_t *list_cell_ptr;
typedef struct {
int size;
list_cell_ptr head;
} list_t;
void list_init(list_t *p_list);
void list_free(list_t *p_list);
void list_push(list_t *p_list, void *data);
void list_unshift(list_t *p_list, void *data);
void *list_pop(list_t *p_list);
void *list_shift(list_t *p_list);
list.c
#include "list.h"
#include <stdlib.h>
#include <string.h>
void list_init(list_t *p_list)
{
memset(p_list, 0, sizeof(list_t));
p_list->head = NULL;
p_list->size = 0;
}
void list_free(list_t *p_list)
{
list_cell_ptr p_cell, p_next;
p_cell = p_list->head;
while (p_cell != NULL) {
p_next = p_cell->next;
memset(p_cell, 0, sizeof(list_cell_t));
free(p_cell);
p_cell = p_next;
}
memset(p_list, 0, sizeof(list_t));
}
void list_push(list_t *p_list, void *data)
{
list_cell_ptr *p_curr_ptr, p_tmp;
p_tmp = (list_cell_ptr)malloc(sizeof(list_cell_t));
memset(p_tmp, 0, sizeof(list_cell_t));
p_tmp->data = data;
p_curr_ptr = &(p_list->head);
while (*p_curr_ptr != NULL) {
p_curr_ptr = &((*p_curr_ptr)->next);
}
p_tmp->next = NULL;
*p_curr_ptr = p_tmp;
p_list->size++;
}
void list_unshift(list_t *p_list, void *data)
{
list_cell_ptr *p_curr_ptr, p_tmp;
p_tmp = (list_cell_ptr)malloc(sizeof(list_cell_t));
memset(p_tmp, 0, sizeof(list_cell_t));
p_tmp->data = data;
p_curr_ptr = &(p_list->head);
p_tmp->next = *p_curr_ptr;
*p_curr_ptr = p_tmp;
p_list->size++;
}
void *list_pop(list_t *p_list)
{
list_cell_ptr *p_curr_ptr = &(p_list->head);
while ((*p_curr_ptr)->next != NULL) {
p_curr_ptr = &((*p_curr_ptr)->next);
}
void *ret = (*p_curr_ptr)->data;
*p_curr_ptr = NULL;
p_list->size--;
return ret;
}
void *list_shift(list_t *p_list)
{
void *ret = p_list->head->data;
list_cell_ptr p_next = p_list->head->next;
p_list->head = p_next;
p_list->size--;
return ret;
}
3 回答
总的来说,C内存管理的一般规则是必须始终明确责任在于释放每一块动态分配的内存,并且无论它在哪里,代码必须注意尽职尽责地履行所有这些职责 . 在您的情况下,将释放为给定列表分配的
struct _list_cell_t
对象的责任的唯一合理位置是在代码中再次从列表中删除这些对象(pop
,shift
和free
函数) .但是,在释放每个此类对象后,您不能再次访问它,因此必须首先存储要在局部变量中返回的
data
指针 . 事实上,你已经这样做了 .有很多方法可以实现细节,但我建议这个范例:
在本地变量中存储指向不再需要的
struct _list_cell_t
的指针 .更新列表的结构以剪切该对象 .
在本地变量中存储指向所需数据的指针 .
通过步骤(1)中记录的指针释放不需要的
struct _list_cell_t
返回数据
在覆盖值并松开您指向的地址之前,您应该使用指针释放内存 . 你有使用该指针来释放内存空间 .
我希望我回答你的问题
你可以使用智能指针 .
这可以使用C中的结构来完成 . 我在C中包含了一个基本的例子 . 它没有实现你拥有的所有函数(只是push和pop),但它应该让你知道智能指针 .
实际上没有其他方法可以在代码和客户端之间共享内存 .