I have a generic linked list implementation with a node struct containing a void* to data and a list struct that holds a reference to head. Now here is my problem a node in the linked list may hold a reference to another linked list via its void*. This causes memory leaks when I free the bigger list containing smaller lists. So I am wondering is there a way to check if the void* is pointing to another list so I follow and free that also or to just data.
If i add a key to the beginning of my struct a magic number that I can check by dereferencing the void* and figure out it is a list?
EDIT: Callers don’t insert the smaller lists they are inserted by my functions I do not want the callers to deal with relasing multiple lists just the one they hold a pointer to.
This question really depends on whose responsibility it is to clean up the entries in the list. If your struct is responsible for cleaning up the memory referenced by the
void *fields, then you have a much bigger problem at hand here, namely that given avoid *referencing some arbitrary block of memory you can never know what the right way to deallocate it is. For example, if you have an implementation of a dynamic array along the lines of the C++std::vector, then yourvoid *might point at a struct that itself contains a pointer, and your list will need to know that it has to descend into that struct to recursively free its dynamically-allocated block. The case you’re describing, where you’re leaking a nested list – is just a special case of this more general issue.If, on the other hand, the list is not responsible for cleaning up the memory referenced by the
void *s it stores, then you shouldn’t worry about this problem at all.If your list does have ownership semantics and is required to clean up the memory for the elements stored in it, I would strongly discourage you from using a magic number to determine whether you have a nested list. Rather, you should probably have the client provide you a function pointer containing a deallocation routine to run on the elements inserted into the list. That way, your code can use the user’s provided cleanup code to ensure that any elements stored in the list are cleaned up.