# mulle_allocator_stdlib_nofree: Purpose and Usage for Static Allocation Patterns

> Discover mulle_allocator_stdlib_nofree's purpose for static allocation. Learn how it uses calloc/realloc for memory needs where individual freeing isn't required, optimizing your C projects.

- Repository: [mulle-c/mulle-allocator](https://github.com/mulle-c/mulle-allocator)
- Tags: how-to-guide
- Published: 2026-03-07

---

**`mulle_allocator_stdlib_nofree` is a singleton allocator that forwards allocation requests to the C standard library (`calloc`/`realloc`) while implementing `free` as a no-operation, making it ideal for static or arena allocation patterns where memory is never reclaimed individually.**

The `mulle-c/mulle-allocator` library provides a pluggable memory management abstraction that decouples allocation strategy from application logic. The `mulle_allocator_stdlib_nofree` singleton serves as a specialized tool for scenarios where allocated memory lives for the entire process duration or is reclaimed in bulk by external mechanisms.

## What is mulle_allocator_stdlib_nofree?

In [`src/mulle-allocator.c`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.c) (lines 157–165), the library defines `mulle_allocator_stdlib_nofree` as a global constant structure:

```c
struct mulle_allocator   mulle_allocator_stdlib_nofree =
{
   calloc,            // allocate & zero‑initialize
   realloc,           // resize
   no_free,           // free‑operation does nothing
   mulle_allocation_fail,
   mulle_allocator_no_aba_abort,
   NULL
};

```

This configuration creates an **indirection layer** over standard C memory functions. While allocation and resizing use the system `calloc` and `realloc`, the `free` member points to `no_free`, a stub function that discards its arguments using `MULLE_C_UNUSED`. Consequently, any memory obtained through this allocator remains allocated until the process terminates, regardless of `free` calls.

According to the documentation in [`assets/dox/TOC.md`](https://github.com/mulle-c/mulle-allocator/blob/main/assets/dox/TOC.md) (lines 20–22), this allocator is explicitly designed to "allocate but never free (for static/arena patterns)".

## When to Use mulle_allocator_stdlib_nofree

Use `mulle_allocator_stdlib_nofree` when individual deallocation is unnecessary or undesirable:

- **Bootstrap phases** — Initialize complex data structures during program startup that persist until process exit, eliminating deallocation overhead.
- **Arena/region allocators** — Build high-level allocators that manage memory in bulk; the OS reclaims all memory when the arena is destroyed or the process ends.
- **Performance-critical sections** — Avoid the computational cost of `free` bookkeeping when object lifetimes are guaranteed to span the entire program execution.
- **Testing harnesses** — Verify that code paths do not rely on `free` being called, or disable leak-checking for specific test scenarios.

**Do not** use this allocator when individual objects must be reclaimed mid-execution, when operating under memory constraints, or when integrating with external libraries that expect `free` to actually release memory back to the system.

## mulle_allocator_stdlib_nofree Code Examples

### Basic Allocation Pattern

The following demonstrates safe allocation where the `free` call is harmless but ineffective:

```c
#include <mulle-allocator/mulle-allocator.h>

int main(void)
{
    // Grab the no‑free allocator singleton
    struct mulle_allocator *alloc = &mulle_allocator_stdlib_nofree;

    // Allocate 256 bytes — memory will never be returned to the OS
    void *buf = mulle_allocator_calloc(alloc, 1, 256);
    /* use buf … */

    // This call is safe but performs no action
    mulle_allocator_free(alloc, buf);
    return 0;
}

```

### Integration with Data Structures

Embed the allocator in structures that manage pooled memory:

```c
struct arena_vector
{
    struct mulle_allocator *allocator;   // points to stdlib_nofree
    void                **items;
    size_t               count;
};

void arena_vector_init(struct arena_vector *v)
{
    v->allocator = &mulle_allocator_stdlib_nofree;
    v->items     = mulle_allocator_malloc(v->allocator, 16 * sizeof(void *));
    v->count     = 0;
}

/* Adding an element — no need to free individual items later */
void arena_vector_push(struct arena_vector *v, void *elem)
{
    v->items[v->count++] = elem;
}

```

### Runtime Detection

Detect if an allocator is the no-free variant using the query helper defined in [`src/mulle-allocator.c`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.c) (lines 46–73):

```c
if (mulle_allocator_is_stdlib_allocator(&mulle_allocator_stdlib_nofree))
{
    printf("Running with a no‑free allocator\n");
}

```

## Runtime Detection and Safety Features

The `mulle_allocator_is_stdlib_allocator()` function provides a reliable way to identify when code is operating with `mulle_allocator_stdlib_nofree`. This is particularly useful in generic libraries that need to adapt their behavior based on allocation guarantees.

Because `free` is implemented as a no-op, calling `mulle_allocator_free()` on memory obtained from this allocator is **completely safe**—it prevents accidental double-free errors and eliminates risks associated with freeing memory through the wrong allocator instance. This safety property makes `mulle_allocator_stdlib_nofree` suitable for subsystem isolation where deallocation discipline might otherwise be error-prone.

## Summary

- **`mulle_allocator_stdlib_nofree`** forwards `calloc` and `realloc` to the C standard library but ignores all `free` requests.
- **Located in** [`src/mulle-allocator.c`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.c) (lines 157–165), this singleton is documented in [`assets/dox/TOC.md`](https://github.com/mulle-c/mulle-allocator/blob/main/assets/dox/TOC.md) as the allocator that "allocates but never frees".
- **Ideal for** static initialization, arena allocation patterns, and performance-critical paths where object lifetimes match process duration.
- **Safe to use** because `free` calls are no-ops, preventing double-free and allocator-mismatch bugs.
- **Detectable at runtime** via `mulle_allocator_is_stdlib_allocator()` (defined in [`src/mulle-allocator.c`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.c) lines 46–73).

## Frequently Asked Questions

### What happens if I call free on memory allocated with mulle_allocator_stdlib_nofree?

Nothing. The allocator's `free` function is implemented as `no_free`, a stub that silently discards its arguments. This is a deliberate safety feature that prevents double-free errors and makes the allocator harmless to use in contexts where `free` might be called defensively.

### How do I check if my current allocator is the no-free variant at runtime?

Use the `mulle_allocator_is_stdlib_allocator()` function declared in [`src/mulle-allocator.h`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.h) and implemented in [`src/mulle-allocator.c`](https://github.com/mulle-c/mulle-allocator/blob/main/src/mulle-allocator.c) (lines 46–73). Pass a pointer to `mulle_allocator_stdlib_nofree` or any allocator instance to verify if it matches the standard library-based no-free singleton.

### Can I use mulle_allocator_stdlib_nofree with third-party libraries?

Only if those libraries do not expect `free` to actually release memory. Since `mulle_allocator_stdlib_nofree` never returns memory to the system, using it with libraries that perform frequent allocations and deallocations will cause unbounded memory growth. Restrict its use to code you control or libraries designed for arena-style allocation.

### Is mulle_allocator_stdlib_nofree thread-safe?

Yes, because it relies on the underlying C standard library functions (`calloc` and `realloc`), which are typically thread-safe on modern systems. However, since `free` is a no-op, there is no synchronization overhead for deallocation operations, making this allocator particularly efficient for concurrent allocation-heavy workloads with static lifetimes.