7 ms·
One slight variation on the getaddrinfo()/freeaddrinfo() approach is what (among many others) GMP [1] and its derivatives do: For every struct or custom type, y
by thxg 4y ago
One slight variation on the getaddrinfo()/freeaddrinfo() approach is what (among many others) GMP [1] and its derivatives do: For every struct or custom type, you systematically get
void type_init(type *t, [...]);
void type_clear(type *t, [...]);
This is essentially explicit constructors and destructors in C, and one can legitimately argue that it is clunky, verbose and error-prone.
However, if we are constrained to a C API, it does have one important practical quality in my experience: Because it is always the same, it eases the mental load on both the API's user and the API's implementer, especially if there are many such types involved.
[1] See e.g. https://gmplib.org/manual/Initializing-Integers https://gmplib.org/manual/Initializing-Integers
- vlovich123 4y agoCoreFoundation at Apple had a similar convention. Any memory obtained by an API named Create or Copy would have similar Delete method that always had to be called.
- throwawaymaths 4y agoEspecially for certain generics (e.g. hashmaps) you might want to have different allocators without creating a whole separate type: for example a global one, a threadlocal arena, etc.
- username223 4y ago> explicit constructors and destructors in C Exactly, and that’s the right way to do it. In a language without implicit destructors/finalizers, you need a way for callers to say “okay, I’m done with this thing.” And even with GC, you need finalizers to take care of non-memory resources. This may be clunky in C, but that’s what you get in a language that makes you be explicit.
- deathanatos 4y ago> and one can legitimately argue that it is clunky, verbose and error-prone. Clunky and verbose, yes, error-prone no. The APIs that do that are generally much more clear about ownership, and thus much easier, IMO, to write correct code for. Much worse is the API that returns you a pointer with no obvious mechanism to free it. Is it tied to the lifetime of an input to the function that returned it? Is it a global and this API is completely thread-unsafe? Am I leaking memory?