Skip to content
HeapAllocatorInit

HeapAllocatorInit

Description

Construct a HeapAllocator with default alignment (1). Use as a designated-initializer at any storage class. The allocator starts empty: no descriptors, no XL regions, no recycled pages; all kernel page mappings happen lazily on the first alloc per class.

HeapAllocator h = HeapAllocatorInit(); void *p = AllocatorAlloc(&h, 64, false); AllocatorFree(&h, p); HeapAllocatorDeinit(&h);

Success

Returns a fully-initialised HeapAllocator value. No OS calls are made; first per-class alloc triggers the lazy page-map.

Failure

Cannot fail at macro-expansion time.

Usage example (Cross-references)

Usage examples (Cross-references)
    #define LOG_FATAL(...)                                                                                                 \
        do {                                                                                                               \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
    #define LOG_ERROR(...)                                                                                                 \
        do {                                                                                                               \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
    #define LOG_INFO(...)                                                                                                  \
        do {                                                                                                               \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
        do {                                                                                                               \
            i32           UNPL(sys_eno)   = (i32)(eno);                                                                    \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
        do {                                                                                                               \
            i32           UNPL(sys_eno)   = (i32)(eno);                                                                    \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
        do {                                                                                                               \
            i32           UNPL(sys_eno)   = (i32)(eno);                                                                    \
            HeapAllocator UNPL(log_alloc) = HeapAllocatorInit();                                                           \
            Str           UNPL(m)         = StrInit(&UNPL(log_alloc));                                                     \
            StrAppendFmt(&UNPL(m), __VA_ARGS__);                                                                           \
    #    endif
    #else
    #    define DefaultAllocatorInit() HeapAllocatorInit()
    #endif
                       .__magic         = DEBUG_ALLOCATOR_MAGIC | MAGIC_VALIDATED_BIT,                                                                 \
                       .footprint_bytes = 0},                                                                                    \
            .heap         = HeapAllocatorInit(),                                                                           \
            .meta         = HeapAllocatorInit(),                                                                           \
            .page         = PageAllocatorInit(),                                                                           \
                       .footprint_bytes = 0},                                                                                    \
            .heap         = HeapAllocatorInit(),                                                                           \
            .meta         = HeapAllocatorInit(),                                                                           \
            .page         = PageAllocatorInit(),                                                                           \
            .config       = (_cfg),                                                                                        \
        };
    
        HeapAllocator h    = HeapAllocatorInit();
        Str           full = StrInit(&h);
        StrAppendFmt(&full, "[{}] [{}:{}] {}\n", (Zstr)NAMES[type], (Zstr)tag, line, (Zstr)msg);
        // we don't know the entry count in advance. The per-entry path
        // string is stack-backed via StrInitStack below.
        HeapAllocator ha = HeapAllocatorInit();
        // dir_get_contents takes `Allocator *` (it's a generic helper used
        // by both typed and erased callers) -- legitimate erasure boundary;
        bool           used_heap = false;
        if (count > STACK_MAX) {
            halloc = HeapAllocatorInit();
            pfds   = (plat_pollfd_t *)AllocatorAlloc(&halloc, sizeof(plat_pollfd_t) * count, true);
            if (!pfds) {
    
    static bool test_basic_alloc_free(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_zeroed_alloc(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_zero_byte_alloc_returns_null(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_free_null_is_noop(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
        // Three allocs of the same size must yield three distinct pointers.
        // After the third alloc, bits 0..2 of bitmap_32 should be set.
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_free_then_alloc_recycles(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
            N                 = HEAP_PAGES_PER_OS_PAGE * SLOTS_PER_32_PAGE + 1
        };
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
        // set after the power-of-two rewrite, so each alloc lands in a
        // distinct class and provisions its own page(s).
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    static bool test_large_alloc_passthrough(void) {
        // > 2 KiB hits the XL path.
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_realloc_same_bin_keeps_pointer(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_realloc_cross_bin_copies(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
    
    static bool test_independent_heaps(void) {
        HeapAllocator h1     = HeapAllocatorInit();
        HeapAllocator h2     = HeapAllocatorInit();
        Allocator    *alloc1 = ALLOCATOR_OF(&h1);
    static bool test_independent_heaps(void) {
        HeapAllocator h1     = HeapAllocatorInit();
        HeapAllocator h2     = HeapAllocatorInit();
        Allocator    *alloc1 = ALLOCATOR_OF(&h1);
        Allocator    *alloc2 = ALLOCATOR_OF(&h2);
    
    static bool test_reject_foreign_pointer(void) {
        HeapAllocator h1     = HeapAllocatorInit();
        HeapAllocator h2     = HeapAllocatorInit();
        Allocator    *alloc1 = ALLOCATOR_OF(&h1);
    static bool test_reject_foreign_pointer(void) {
        HeapAllocator h1     = HeapAllocatorInit();
        HeapAllocator h2     = HeapAllocatorInit();
        Allocator    *alloc1 = ALLOCATOR_OF(&h1);
        Allocator    *alloc2 = ALLOCATOR_OF(&h2);
    
    static bool test_reject_double_free(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
        void         *p     = AllocatorAlloc(alloc, 32, false);
    
    static bool test_reject_misaligned_pointer(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
        u8           *p     = (u8 *)AllocatorAlloc(alloc, 64, false);
    
    static bool test_reject_mid_xl_pointer(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
        size          n     = 16 * 1024;
        // allocator -- not through `dbg` -- so its own storage isn't
        // counted as a leak by the very report we're about to generate.
        HeapAllocator scratch = HeapAllocatorInit();
        Str           out     = StrInit(&scratch);
        DebugAllocatorReportLeaks(&dbg, &out);
        (void)p;
    
        HeapAllocator scratch = HeapAllocatorInit();
        Str           out     = StrInit(&scratch);
        DebugAllocatorReportLeaks(&dbg, &out);
        typedef Vec(int) IntVec;
    
        HeapAllocator local_heap = HeapAllocatorInit();
        // intentional bypass: no public setter on `Allocator` for effort /
        // retry_limit -- pre-seeded directly so the inheritance path below
        ok               = ok && (rec != NULL) && (rec->alloc_trace_n >= 2);
    
        HeapAllocator scratch = HeapAllocatorInit();
        Str           out     = StrInit(&scratch);
        DebugAllocatorReportLeaks(&dbg, &out);
        u32 n            = ok ? rec->alloc_trace_n : 0;
    
        HeapAllocator scratch = HeapAllocatorInit();
        Str           out     = StrInit(&scratch);
        DebugAllocatorReportLeaks(&dbg, &out);
    static Allocator *fixture_alloc(void) {
        if (!g_fixture_heap_ready) {
            g_fixture_heap       = HeapAllocatorInit();
            g_fixture_heap_ready = true;
        }
        // Float backed by a SEPARATE heap so only the formatter scratch shows
        // up in dbg's live count.
        HeapAllocator fa = HeapAllocatorInit();
        Float         v  = FloatFromStr("12345.67", ALLOCATOR_OF(&fa));
        Allocator     *adbg = ALLOCATOR_OF(&dbg);
    
        HeapAllocator fa = HeapAllocatorInit();
        Float         v  = FloatFromStr("0.0", ALLOCATOR_OF(&fa));
        Allocator     *adbg = ALLOCATOR_OF(&dbg);
    
        HeapAllocator fa = HeapAllocatorInit();
        Float         v  = FloatFromStr("3.14159", ALLOCATOR_OF(&fa));
        Allocator     *adbg = ALLOCATOR_OF(&dbg);
    
        HeapAllocator fa = HeapAllocatorInit();
        Float         v  = FloatFromStr("42", ALLOCATOR_OF(&fa));
    
    bool test_leak_write_str_freed(void) {
        HeapAllocator va = HeapAllocatorInit();
        Str           s  = StrInit(ALLOCATOR_OF(&va));
        StrAppendFmt(&s, "payload");
    
    bool test_leak_write_int_freed(void) {
        HeapAllocator va = HeapAllocatorInit();
        Int           v  = IntFromStr("123456789012345678901234567890", ALLOCATOR_OF(&va));
        LEAK_WRITE_PRELUDE();
    
    bool test_leak_write_float_freed(void) {
        HeapAllocator va = HeapAllocatorInit();
        Float         v  = FloatFromStr("2.718281828", ALLOCATOR_OF(&va));
        LEAK_WRITE_PRELUDE();
    
    bool test_leak_write_bitvec_freed(void) {
        HeapAllocator va = HeapAllocatorInit();
        BitVec        v  = BitVecInit(ALLOCATOR_OF(&va));
        BitVecResize(&v, 12);
    // 1794: _write_Str `{x}` (FMT_FLAG_HEX) per-byte `hex` scratch.
    bool test_leak_write_str_hex_per_byte_freed(void) {
        HeapAllocator sa = HeapAllocatorInit();
        Str           s  = StrInit(ALLOCATOR_OF(&sa));
        for (int i = 0; i < 8; ++i)
    // 2286: _write_Float default-decimal `temp` (via float_try_to_decimal_str).
    bool test_leak_write_float_default_freed(void) {
        HeapAllocator fa = HeapAllocatorInit();
        Float         f  = FloatFromStr("12345678901234567890123456789012345678901234567890.5", ALLOCATOR_OF(&fa));
        LEAK_WRITE_PRELUDE();
    // reserve_vec zeroes it.
    static bool reserve_zero_grown_region(int probe_index) {
        HeapAllocator heap = HeapAllocatorInit();
    
        typedef Vec(int) IntVec;
        WriteFmt("Testing reserve at the overflow boundary returns false (112:42)\n");
    
        HeapAllocator heap = HeapAllocatorInit(); // alignment 1 -> aligned_size == 1
    
        typedef Vec(char) CharVec;
        // that the pointer-based allocator stored in the vector reflects each
        // allocator's settings.
        HeapAllocator h_default = HeapAllocatorInit();
        HeapAllocator h8        = HeapAllocatorInitAligned(8);
        HeapAllocator h16       = HeapAllocatorInitAligned(16);
    // 112 (stats.peak_bytes_in_use = in_use -> = 42): same for peak.
    static bool test_al_reset_stats_preserves_outstanding(void) {
        HeapAllocator heap  = HeapAllocatorInit();
        Allocator    *alloc = ALLOCATOR_OF(&heap);
Last updated on