I'm writing a library and want to make it absolutely resource-agnostic which also means that library should live with user-supplied memory allocation functions. Library allows user to set their own error handler function too, which are called with an error message as an argument, like that:
typedef void (*error_handler)(const char* msg);
Library code prepares error message by itself, somehow like that (with case when message formatting fails being omitted):
char buf[BUF_SIZE];
snprintf(buf, BUF_SIZE, "Oops found at file '%s' line %d", __FILE__, __LINE__);
But can I be sure that snprintf will not allocate even more memory for its internal usage with malloc, obviously bypassing user-supplied allocation routines? Man page in my Linux system keeps silence on that.
Like any library routine, sprintf
and snprintf
may or may not allocate memory for internal use.
They will not allocate memory for the resulting string. That memory must be allocated somehow by the caller, and its address passed as the first argument. If the allocated memory isn't big enough, then sprintf
will have undefined behavior (since there's no way to tell it how much space is available), and snprintf
will truncate the result (assuming the size argument is accurate).
If an implementation of sprintf
or snprintf
allocates memory and doesn't arrange for it to be released, that would be a memory leak. Such a leak would not actually violate the language standard (which has little to say about resource allocation), but it would be considered a bug in that implementation.
In particular, if your own code uses its own memory allocator rather than malloc
, any library functions you call could call malloc
internally, unless you use some system-specific feature to cause calls to malloc
, even in the standard library, to call your allocator instead. fopen()
, for example, is particularly likely to allocate memory for buffers.
If you do something to replace the standard library's calls to malloc
with calls to your own allocator, you'll need to be sure that you also replace any calls to realloc
, calloc
, and free
, and possibly one or more system-specific routines. For example, cleanup code that runs when your program finishes will close open files, which might involve calls to free
.