I noticed that it is a common idiom in C to accept an un-malloc
ed pointer as a second argument instead of returning a pointer. Example:
/*functi
I usually don't make a fixed choice, I cleanly put it into its own library and provide the best of both worlds.
void node_init (node_t *n);
void node_term (node_t *n);
node_t *node_create ()
{
node_t *n = malloc(sizeof *n);
/* boilerplate error handling for malloc returning NULL goes here */
node_init(n);
return n;
}
void node_destroy (node_t *n)
{
node_term(n);
free(n);
}
For every malloc there should be a free, thus for every init there should be a term and for every create there should be a destroy. As your objects grow more complex, you will find that you begin to nest them. Some higher level object may use a node_t list for internal data management. Before freeing this object, the list must be freed first. _init and _term care for this, completely hiding this implementation detail.
There can be decisions about further details, e.g. destroy may take a node_t **n and set *n to NULL after freeing it.