#define TM_MEMORY_TRACKER_SCOPE__NONE 0xffffffffu
Reserved `mem_scope` used for untracked allocations.
If you give an allocator this scope, it's allocations will not be tracked. Be careful with using
this as the goal of the memory tracker is to track as many allocations as possible.
A legitimate use for this is for the temporary memory allocator. There is no need to track all
the allocations made by the temporary memory allocator (since they're short-lived anyway).
Instead we just track the allocations that the temporary memory allocator makes to its `backing`
Information about allocations in a certain scope. Note that `allocated_bytes` and
`allocation_count` are *exclusive*, i.e., they do not include the allocations in child scopes. If
you want an inclusive count, you will have to sum the allocations yourself.
typedef struct tm_memory_tracker_scope_data_t
// Description of the scope.
const char *desc;
// Bytes allocated in the scope.
TM_ATOMIC uint64_t allocated_bytes;
// Number of allocations in the scope.
TM_ATOMIC uint64_t allocation_count;
// Index of parent scope.
// Number of children of this scope.
// True if tracing is enabled for this scope.
// Number of traces for this scope.
API for the global memory allocation tracker.
The tracker is implicitly created when first called.
Called at the end of the program, when all created scopes should have been released. Checks
that all scopes created by `create_scope()`
have been destroyed.
uint32_t (*create_scope)(const char *desc, uint32_t parent_scope);
Creates a new "scope" for tracking memory allocations. The tracker will keep track of the
amount of memory allocated in each scope, and when the scope is destroyed, it will check that
all memory allocated in the scope has been freed.
`desc` is a description of the scope for debugging and tracking purposes. `parent_scope`
specifies the parent scope that "owns" this scope. All child scopes must be destroyed before
their parent scope is destroyed.
`0` is considered the "root scope". Use that as a `parent_scope` for allocators that don't
If you use `TM_MEMORY_TRACKER_SCOPE__NONE`
as the `parent` scope, the scope created will be
excluded from the `check_for_leaked_scopes()`
check. I.e., you do not have to explicitly
destroy the scope. This can be useful for "global" allocations that live for the duration of
the application, but you should be a little bit careful with using it, since we won't be able
to do memory leak detection for such allocations.
void (*destroy_scope)(uint32_t s);
Destroys a scope created by `create_scope()`
. This function will assert that all memory in
the scope has been freed.
void (*destroy_scope_allowing_leaks)(uint32_t scope, uint64_t max_leaked_bytes);
but allows leaking up to `max_leaked_bytes` bytes without generating an
error. This can be used if the scope is being used by third-party code that is leaking stuff
beyond our control.
It should not be left permanently in the code, rather the goal should be to get the third
party code cleaned up so it doesn't leak anymore.
void (*record_realloc)(void *old_ptr, uint64_t old_size,
void *new_ptr, uint64_t new_size, const char *file, uint32_t line, uint32_t scope);
Records an allocation from an allocator.
uint64_t (*allocated_bytes)(const uint32_t scope);
Returns the total number of bytes currently allocated in the specified scope.
uint64_t (*allocation_count)(const uint32_t scope);
Returns the total number of allocations in the specified scope.
void (*set_scope_tracing)(uint32_t scope, bool enabled);
Enables or disables tracing for the specified scope. When tracing is enabled, the file and
line number of all allocations are recorded. If there are any leaks when the scope is
destroyed, the locations of all the allocations that leaked will be printed.
Typically you enable tracing for a scope after `destroy_scope()`
has alerted that the scope
is leaking memory to find out more details about where the leak occurs.`
/* carray */ tm_memory_tracker_scope_data_t *(*scope_data_snapshot)(struct tm_temp_allocator_i *ta);
Returns a snapshot of the scope data, allocated using `ta`. Note that the snapshot may
include unused scopes (with `desc` set to NULL).
/* carray */ tm_memory_tracker_trace_data_t *(*trace_data_snapshot)(struct tm_temp_allocator_i *ta);
Returns a snapshot of the trace data, allocated using `ta`.