I think I'm a bit confused with memory management conventions in C.
Let's say we have a struct that dynamically allocate data on the heap.
This struct provides _alloc()
and _free()
functions for allocating and freeing this struct on the heap.
Here's a example with a simple vector struct:
struct vec_t {
int *items;
size_t size;
size_t capacity;
};
struct vec_t *vec_alloc(void)
{
struct vec_t *vec = malloc(sizeof(struct vec_t));
vec->items = NULL;
vec->size = 0;
vec->capacity = 0;
return vec;
}
void vec_free(struct vec_t *vec)
{
free(vec->items);
free(vec);
}
void vec_push(struct vec_t *vec, int item)
{
if (vec->size == vec->capacity)
{
size_t new_capacity = vec->capacity > 0 ? (vec->capacity + 1) * 2 : 5;
vec->items = realloc(vec->items, new_capacity * sizeof(int));
}
vec->items[vec->size++] = item;
}
Now let's assume we don't use _alloc()
or _free()
and instead decide to allocate this struct on the stack.
We then indirectly allocate data on the heap via the stack allocated struct (my_vec.items
)
void main()
{
vec_t my_vec;
vec_push(&my_vec, 8); // allocates memory
// vec_destroy(&my_vec); // PROBLEM
return 0;
}
Now we have a problem: we don't want to free the struct (my_vec
) as it's on the stack, but we need to free the data allocated by the struct on the heap (my_vec.items
).
I believe this is either a design issue or a convention issue, or a mix of both.
I've seen people add some extra functions _init()
and _deinit()
in addition to _alloc()
and _free()
.
void vec_init(struct vec_t *vec)
{
vec->items = NULL;
vec->size = 0;
vec->capacity = 0;
}
void vec_deinit(struct vec_t *vec)
{
free(vec->items);
}
Would it make sense to free memory allocated by the struct in _deinit()
?
If this approach is corret, am I correct saying that a struct allocated on the stack like this always need to be _init()
and _deinit()
?