The C free() API gives libraries and functions useful freedom

September 15, 2022

A while back I wrote about how free()s API means that (C) memory allocation has to save some metadata, either explicitly or implicitly, because you don't pass in the size of what you're freeing. I happen to feel that this is still a decent API for C, but beyond that there's another little advantage to this API, which is that no one needs to know how big an allocated object is. There are at least three uses for this.

The first use is the one traditionally used by advanced C memory allocation systems. Many allocations (especially for small sizes) will have their size rounded up a bit, leaving extra unused space behind the returned object. If this object is then passed to realloc(), it's possible for it to be reallocated larger in place, without any memory copying having to be done. The realloc() API specifically allows this behavior, and doesn't require that a different pointer be returned than was passed in.

(Realloc can also be used to shrink the allocation, which can easily be done in place, although I think that usage is a lot less common.)

The second use is that a library can (theoretically) transparently expand the size of an object that it returns and that you free later yourself, especially if the object and its size is completely opaque. Similarly, a library can actually return several differently sized objects that you treat uniformly; as far as you're concerned they're a black box that you eventually call free() on. There are some cautions in practice, since C programmers have traditionally been very ingenious about finding ways to actually depend on the size of the thing you return.

(C strings are kind of this; things that return dynamically allocated strings generally don't promise that they'll be any specific size.)

The third use is what some people proposed as the solution to how malloc() and free() affect C APIs in the case of gethostbyname(). Although a 'struct hostent' contains pointers to various other things, you can pack all of those things together into a single memory allocation that has the 'struct hostent' at the start (effectively you allocate a little arena and then manually manage it). Because this is a single memory allocation, you can return a single pointer to it and the caller can still free everything with a single call to free(). I'm not convinced that this is a good API, but it's certainly one that free()'s API makes possible.

Written on 15 September 2022.
« Grafana Loki doesn't duplicate a central syslog server (or vice versa)
The problem of network tunnels and (asymmetric) routing »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Sep 15 22:17:15 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.