链表节点释放数据的职责应该如何确定?

How should I decide the responsibility of freeing data in nodes of linked list?

单链表的C代码如下,

struct singly_linked_node {
    void *data;
    struct singly_linked_node *next;
}

struct singly_linked_list {
    struct singly_linked_node *head;
}

struct singly_linked_list * singly_linked_list_malloc() {
    struct singly_linked_list *list = malloc(sizeof(struct singly_linked_list));
    if (list == NULL) {
        return NULL;
    }
    list->head = NULL;
    return list;
}

// inserts specified data specified index
// by adding a (internally initialized) new node
// and returns EXIT_(SUCCESS|FAILURE)
int singly_linked_list_insert(struct singly_linked_list *list, size_t index, void *data);

// deletes the node at specified index
// and returns the data of the deleted(freed) node
void* singly_linked_list_delete(struct singly_linked_list *list, size_t index);

如您所见,我试图让呼叫者只关注 ..._list 而不是 ..._node

我需要写一个函数释放singly_linked_list的指针。

void singly_linked_list_free(struct singly_linked_list *list) {
    assert(list != NULL);

    // what about nodes in the list?

    // what about data in each node?

    free(list);
}

我应该 free(list) 吗?

我至少应该释放列表中的所有节点吗?

void singly_linked_list_free(struct singly_linked_list *list) {
    assert(list != NULL);

    for (struct singly_linked_node *i = list->head; i != NULL; i = i->next) {
        void *data = i->data; // responsibility?
        free(i);
    }

    free(list);
}

或者我是否应该释放所有数据指针?

void singly_linked_list_free(struct singly_linked_list *list) {
    assert(list != NULL);

    for (struct singly_linked_node *i = list->head; i != NULL; i = i->next) {
        free(i->data);
        free(i);
    }

    free(list);
}

如评论中所述,您负责节点和列表本身,但不负责数据,因为您无法知道(在任何情况下)数据是驻留在堆上还是堆栈上。

像这样简单地创建一个 foreach 方法:

void singly_linked_list_foreach (
    struct singly_linked_list *list,
    void (*callback)(void*)
){
    //for every node in the list
    //call 'callback' with the data as parameter, e.g.
    //callback(item->data);
}

然后,如果您想释放列表中的所有数据:

singly_linked_list_foreach(list, free);

为了更舒适,重新声明您的 list_free 函数,例如:

void singly_linked_list_free (
    struct singly_linked_list *list, 
    int free_data
){
    if (free_data)
        singly_linked_list_foreach(list, free);
    //free all nodes
    //free list
}