Parametrizing C library by an allocator

I am writing a C library (in Zig), and I want to parametrize the library by an allocator.

What’s the best way to expose allocator in the C API? I haven’t done this previously, and my heuristic says “do as Lua does”:

https://www.lua.org/manual/5.3/manual.html#lua_Alloc

typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

This is a Swiss army knife API with a “realloc” that can do alloc (if old size is 0), free (if new size is 0) or realloc (general case), and which his also parametrized by user data, such that it is a proper closure.

Would I have any problems with this?

3 Likes

I don’t see any problem.
Providing the size when freeing is a good practice for catching errors.
Don’t miss Chris Wellons “simple allocator’s best friend”: So you want custom allocator support in your C library.

2 Likes

Ah, at the end of the post Chris actually points at the same lua_Alloc! That’s a strong endorsement!

1 Like

I have done this a few times before, that single universal function has always been quite enough for all my needs.

A full-blown allocator interface is something like what SQLite does, with a vtable of multiple methods and a context pointer.

But unless you have very sophisticated allocation needs (e.g. your library is a database :wink: ), replicating std.mem.Allocator interface or even just a single realloc function like suggested above should be sufficient to your needs.

1 Like

FWIW what I’m missing most in my own C library allocator interface is a calloc hook which returns zeroed memory (I just don’t like the calloc function signature at all).

AFAIK on the OS level the zeroing can be done more efficiently than malloc+memset for entire memory pages. Not sure if that’s all that relevant in C libraries where memory allocation frequency is very low and mostly happens at startup anyway though.

very optimistic and charitable :smile:

2 Likes