Skip to content
DebugAllocatorLiveBytes

DebugAllocatorLiveBytes

Description

Total user-requested bytes still outstanding, summed by the allocate / deallocate hooks into bytes_in_use.

Parameters

Name Direction Description
self in DebugAllocator instance, or NULL.

Success

Returns the outstanding-bytes count. No state is touched.

Failure

Returns 0 when self is NULL.

Usage example (Cross-references)

Usage examples (Cross-references)
    }
    
    size DebugAllocatorLiveBytes(const DebugAllocator *self) {
        if (!self)
            return 0;
    // Convenience: a test passes iff `ok` held AND the DebugAllocator has no
    // outstanding allocations after the test released everything it owns.
    #define LEAK_CLEAN(dbg) (DebugAllocatorLiveCount(&(dbg)) == 0 && DebugAllocatorLiveBytes(&(dbg)) == 0)
    
    // Leak-only config: live-count tracking, NO per-alloc stack-trace / canary /
        DnsResponseDeinit(&resp);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        DnsResponseDeinit(&resp);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        DnsResponseDeinit(&resp);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        bool ok = p1 && p2;
        ok      = ok && DebugAllocatorLiveCount(&dbg) == 2;
        ok      = ok && DebugAllocatorLiveBytes(&dbg) == (64 + 128);
    
        AllocatorFree(adbg, p1);
        AllocatorFree(adbg, p1);
        ok = ok && DebugAllocatorLiveCount(&dbg) == 1;
        ok = ok && DebugAllocatorLiveBytes(&dbg) == 128;
    
        AllocatorFree(adbg, p2);
        AllocatorFree(adbg, p2);
        ok = ok && DebugAllocatorLiveCount(&dbg) == 0;
        ok = ok && DebugAllocatorLiveBytes(&dbg) == 0;
        ok = ok && DebugAllocatorOverflows(&dbg) == 0;
    
        bool ok = DebugAllocatorLiveCount(&dbg) == 2;
        ok      = ok && DebugAllocatorLiveBytes(&dbg) == (32 + 48);
    
        DebugAllocatorDeinit(&dbg); // logs the leaks
        ok        = ok && (grown != NULL) && (grown[0] == 'h') && (grown[15] == '!');
        ok        = ok && (DebugAllocatorLiveCount(&dbg) == 1);
        ok        = ok && (DebugAllocatorLiveBytes(&dbg) == 200);
    
        if (grown)
        void *p  = AllocatorAlloc(adbg, 64, true);
        bool  ok = (p != NULL) && (DebugAllocatorLiveCount(&dbg) == 1);
        ok       = ok && (DebugAllocatorLiveBytes(&dbg) == 64);
        ok       = ok && (((u64)p & 0xfff) == 0); // page-aligned
        // self->bytes_in_use is surfaced by DebugAllocatorLiveBytes. A
        // mutated `-=` underflows to a huge u64 instead of 100.
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 100);
    
        if (p)
        if (p)
            AllocatorFree(adbg, p);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        return ok;
        // No live record / bytes for a failed alloc.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        }
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        // The allocation is untouched -- still one live record of 64 bytes.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 1);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 64);
    
        if (p)
        ok         = ok && (grown[63] == 0x6B);
        ok         = ok && (DebugAllocatorLiveCount(&dbg) == 1);
        ok         = ok && (DebugAllocatorLiveBytes(&dbg) == 200);
    
        if (grown)
            ok = ok && (shrunk[i] == (u8)(i + 1));
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 1);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 8);
    
        if (shrunk)
    // A test passes iff `ok` held AND the DebugAllocator has no outstanding
    // allocations after the test released everything it owns.
    #define LEAK_CLEAN(dbg) (DebugAllocatorLiveCount(&(dbg)) == 0 && DebugAllocatorLiveBytes(&(dbg)) == 0)
    
    typedef Graph(int) IntGraph;
    #include "../Util/TestRunner.h"
    
    #define LEAK_CLEAN(dbg) (DebugAllocatorLiveCount(&(dbg)) == 0 && DebugAllocatorLiveBytes(&(dbg)) == 0)
    
    // Leak-only config: live-count tracking with NO per-alloc stack-trace capture,
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        FloatDeinit(&v);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        FloatDeinit(&v);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        FloatDeinit(&v);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        FloatDeinit(&v);
        IntDeinit(&value);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        FloatDeinit(&value);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
    #define LEAK_WRITE_EPILOGUE()                                                                                          \
        StrDeinit(&out);                                                                                                   \
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);                           \
        DebugAllocatorDeinit(&dbg);                                                                                        \
        return ok
        ok = ok && StrAppendFmt(&out, "{}", s) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        StrDeinit(&s);
        ok = ok && StrAppendFmt(&out, "{}", v) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        IntDeinit(&v);
        ok = ok && StrAppendFmt(&out, "{}", v) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        FloatDeinit(&v);
        ok = ok && StrAppendFmt(&out, "{}", v) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        BitVecDeinit(&v);
        bool           ok  = StrAppendFmt(&out, "{x}", s) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        StrDeinit(&s);
        ok = ok && StrAppendFmt(&out, "{}", f) && (StrLen(&out) > 0);
        StrDeinit(&out);
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        FloatDeinit(&f);
        Zstr           p   = input;
        StrReadFmt(p, fmt, s); // reader frees s on the unterminated/error branch
        bool ok = (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        return ok;
        Zstr           p   = "aaaaaaaaaaaaaaaaaaaaaaaa\\q"; // 24 'a' + invalid \q
        StrReadFmt(p, "{}", s);
        bool ok = (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        return ok;
        StrReadFmt(p, "{}", bv);
        BitVecDeinit(&bv);
        bool ok = (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        return ok;
        StrReadFmt(p, "{}", fv);
        FloatDeinit(&fv);
        bool ok = (DebugAllocatorLiveCount(&dbg) == 0) && (DebugAllocatorLiveBytes(&dbg) == 0);
        DebugAllocatorDeinit(&dbg);
        return ok;
        // The stripped-away old value buffer must already be freed.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        // The parser's local key copy must already be freed.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        // The parser's local value copy must already be freed.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
        // Every transient lookup key must already be freed.
        ok = ok && (DebugAllocatorLiveCount(&dbg) == 0);
        ok = ok && (DebugAllocatorLiveBytes(&dbg) == 0);
    
        DebugAllocatorDeinit(&dbg);
Last updated on