C 链表 - 何时释放分配的内存

标签 c memory-management linked-list malloc free

我有一个简单的链表实现,带有push、pop、unshift和shift函数来根据需要添加/删除数据。我想确保我的实现在通过调用 pop 和 shift 检索数据时不会泄漏内存。

如何释放通过 malloc 分配的内存,同时将数据返回给调用者?

列表.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);
<小时/>

列表.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;
}

最佳答案

How do I go about freeing memory which has been allocated via malloc, while also returning the data to the caller?

总的来说,C 内存管理的一般规则是,必须始终清楚释放每 block 动态分配的内存的责任在哪里,无论它在哪里,代码都必须小心地履行所有这些责任,不能失败。在您的情况下,释放为给定列表分配的 struct _list_cell_t 对象的唯一合理位置是在再次从列表中删除这些对象的代码中(pop code>、shiftfree 函数)。

但是,在释放每个此类对象后,您不得再次访问它,因此您必须首先将要返回的 data 指针存储在局部变量中。事实上,您已经这样做了。

有很多方法可以实现细节,但我建议使用这种范例:

  1. 将不再需要的struct _list_cell_t指针存储在局部变量中。
  2. 更新列表的结构以删除该对象。
  3. 将指向所需数据的指针存储在局部变量中。
  4. 通过步骤(1)中记录的指针释放不需要的struct _list_cell_t
  5. 返回数据

关于C 链表 - 何时释放分配的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42028271/

相关文章:

c - 如果 argv[] 是一个指针数组,那么 printf ("%s", argv[]) 如何工作?

c++ - 测量(自定义)分配器的执行时间?

android ion, ION_IOC_IMPORT 的 ioctl 返回 <0, errno = 9

iOS - 查看高分辨率图像

java - Intellij IDEA 编辑器中的光标导航滞后

java - 链表栈,推到底部而不是顶部

c - 双向链表问题?

c - 我的链表在第一次迭代后没有运行

调用的对象类型 'void'不是函数或函数指针

c - 静态函数和具有 "hidden"可见性属性的函数之间的实际区别是什么?