How mulle_alloca_do_extract Works: When to Use It Instead of mulle_free
Use mulle_alloca_do_extract to transfer ownership of memory from a mulle_alloca_do block to the surrounding scope, whereas mulle_free only releases heap memory you already own.
The mulle_alloca_do_extract macro in the mulle-c/mulle-allocator repository provides a safe mechanism to extract heap-allocated buffers from temporary alloca blocks. Unlike mulle_free, which simply deallocates existing heap memory, extraction handles the transition from stack-based temporary storage to persistent heap memory that survives beyond the alloca block scope.
What Is mulle_alloca_do_extract?
mulle_alloca_do_extract is a macro defined in src/mulle-alloca.h that extracts the allocated buffer from a mulle_alloca_do block and transfers ownership to a variable in the outer scope. This is essential when you need to access the allocated data after the alloca block exits.
A mulle_alloca_do block allocates a flexible array that lives on the stack while the requested size remains small, automatically falling back to heap allocation via mulle_malloc when the size exceeds the stack limit. The block normally frees the buffer automatically upon exit, but mulle_alloca_do_extract intercepts this process to preserve the data.
How mulle_alloca_do_extract Works
The extraction macro performs four critical operations to safely transition memory ownership:
Stack Detection and Heap Fallback
First, mulle_alloca_do_extract detects whether the variable name still points to the temporary stack buffer (internally stored in name__storage). If the buffer resides on the stack, the macro allocates a fresh heap block of the same size using mulle_malloc and copies the stack contents into it.
Ownership Transfer and Nulling
The macro then assigns the resulting heap pointer to the receiver variable supplied by the caller. Finally, it nulls the original name variable so that the automatic cleanup logic inside mulle_alloca_do will not attempt to free the memory again.
In src/mulle-alloca.h (lines 39-52), this logic ensures that after extraction, the alloca block exits cleanly without touching the transferred memory.
mulle_alloca_do_extract vs mulle_free
Understanding the distinction between these two operations prevents undefined behavior and memory leaks.
-
mulle_alloca_do_extract(name, receiver): Transfers ownership from amulle_alloca_doblock to the caller. Handles both stack-to-heap copying and simple pointer transfer for already-heap-allocated buffers. Defined insrc/mulle-alloca.h. -
mulle_free(pointer): An inline wrapper around_mulle_allocator_freedefined insrc/mulle-allocator.h(lines 47-49). It releases a heap block that already belongs to the caller but performs no stack-buffer handling.
Critical distinction: Calling mulle_free on a pointer that still references the temporary stack buffer created by mulle_alloca_do invokes undefined behavior, as stack memory is not heap-allocated.
| Situation | Use mulle_alloca_do_extract |
Use mulle_free |
|---|---|---|
Allocating with mulle_alloca_do and needing data after the block ends (e.g., returning from a function) |
✅ Extract to a new heap block | ❌ Not applicable (no heap block exists yet) |
Already own a heap-allocated buffer from mulle_malloc and want to release it |
❌ Extraction unnecessary | ✅ Call mulle_free |
| Handing an existing heap allocation to another scope without copying | ✅ Transfers ownership and nulls the original | ❌ Block would later free it again |
Freeing memory obtained from mulle_calloc or similar |
❌ Irrelevant | ✅ Use mulle_free |
Practical Code Examples
Returning Data from a Function
When building a dynamically sized string inside a mulle_alloca_do block, use extraction to return the result to the caller:
/* Example: returning a dynamically sized string built inside a mulle_alloca_do block */
char *make_message( const char *fmt, ... )
{
char *msg;
mulle_alloca_do( buffer, char, 128 ) // buffer may be stack or heap
{
va_list ap;
va_start( ap, fmt );
vsnprintf( buffer, (size_t)buffer__count, fmt, ap );
va_end( ap );
/* Need the string after the block – extract it */
mulle_alloca_do_extract( buffer, msg ); // msg now points to heap memory
} // automatic free does nothing (buffer == NULL)
return msg; // caller must later mulle_free(msg)
}
/* Caller side */
int main(void)
{
char *s = make_message( "Hello %s!", "world" );
puts( s );
mulle_free( s ); // ordinary heap free
return 0;
}
Transferring Ownership to Another API
When the allocation is already on the heap (size exceeded the stack limit), extraction simply transfers the pointer without copying:
/* Example: handing a heap-allocated buffer to another API without copying */
void process_data( void *data, size_t size );
void use_alloca_and_pass( size_t needed )
{
void *tmp;
mulle_alloca_do( tmp, void, needed )
{
/* Fill the buffer … */
/* The allocation is already on the heap (size > stack limit) */
mulle_alloca_do_extract( tmp, tmp ); // just transfers ownership
} // automatic free does nothing because tmp == NULL
process_data( tmp, needed ); // tmp now owned by the callee
/* callee must eventually call mulle_free(tmp) */
}
Summary
mulle_alloca_do_extractsafely transitions memory frommulle_alloca_doblocks to persistent heap storage, handling both stack-to-heap copying and direct ownership transfer.- The macro nulls the original variable to prevent double-free errors when the alloca block exits.
mulle_freeonly releases heap memory already owned by the caller and must never be used on temporary stack buffers from alloca blocks.- Both macros are defined in the mulle-c/mulle-allocator repository:
mulle_alloca_do_extractinsrc/mulle-alloca.h(lines 39-52) andmulle_freeinsrc/mulle-allocator.h(lines 47-49).
Frequently Asked Questions
What is the difference between mulle_alloca_do_extract and mulle_free?
mulle_alloca_do_extract transfers ownership of memory from a mulle_alloca_do block to the surrounding scope, copying stack data to the heap if necessary. mulle_free simply deallocates heap memory that the caller already owns, with no stack-buffer handling or copying logic.
Can I use mulle_free on memory allocated with mulle_alloca_do?
No. Calling mulle_free on a pointer that references the temporary stack buffer created by mulle_alloca_do invokes undefined behavior because the memory is not heap-allocated. Always use mulle_alloca_do_extract to transition the data to the heap first, then use mulle_free later on the extracted pointer.
Does mulle_alloca_do_extract copy data when extracting?
Only if the buffer currently resides on the stack. If mulle_alloca_do allocated the buffer on the heap due to size limits, mulle_alloca_do_extract simply assigns the pointer to the receiver and nulls the original without copying data. If the buffer is on the stack, the macro allocates new heap memory and copies the contents.
Who owns the memory after calling mulle_alloca_do_extract?
After extraction, the receiver variable specified in the macro call owns the heap memory. The original alloca variable is nulled, so the automatic cleanup in the mulle_alloca_do block does nothing. The caller is responsible for eventually calling mulle_free on the extracted pointer to prevent memory leaks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →