With following C code of a singly linked list,
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);
As you can see, I'm trying to make callers concentrate only on the ..._list
not ..._node
.
I need to write a function frees a pointer of 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);
}
Should I just free(list)
?
Should I, at least, free all nodes in the 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);
}
Or should I even free all data pointers?
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);
}
As mentioned in the comments, you are responsible for the nodes and the list itself but not for the data, since you cannot know (in every case) if the data resides on the heap or on the stack.
Simply create a foreach method like this:
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);
}
Then if you want to free all the data in your list:
singly_linked_list_foreach(list, free);
For more comfort, redeclare your list_free function like:
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
}