# memory_tracker.h ## Overview
Provides functionality for tracking memory allocations so that leaks can be detected.
## Index
`struct tm_memory_tracker_scope_data_t`
`struct tm_memory_tracker_trace_data_t`

`struct tm_memory_tracker_api`

## API
~~~c #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` allocator.
### `struct tm_memory_tracker_scope_data_t`
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. ~~~c 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. uint32_t parent; // Number of children of this scope. uint32_t num_children; // True if tracing is enabled for this scope. bool tracing_enabled; TM_PAD(3); // Number of traces for this scope. uint32_t trace_count; } tm_memory_tracker_scope_data_t; ~~~
### `struct tm_memory_tracker_trace_data_t`
Data for one traced allocation. Note that tracing must be explicitly enabled for a scope with `set_scope_tracing()` for trace data to be recorded. ~~~c typedef struct tm_memory_tracker_trace_data_t { // File where this allocation occurred. const char *file; // Line where this allocation occurred. uint32_t line; // Scope that this trace belongs to. uint32_t scope; // Bytes allocated for this trace. uint64_t allocated_bytes; // Number of allocations for this trace. uint64_t allocation_count; } tm_memory_tracker_trace_data_t; ~~~
### `struct tm_memory_tracker_api`
API for the global memory allocation tracker. !!! NOTE The tracker is implicitly created when first called. #### `check_for_leaked_scopes()` ~~~c void (*check_for_leaked_scopes)(void); ~~~ 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. #### `create_scope()` ~~~c 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 have parents. 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. #### `destroy_scope()` ~~~c 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. #### `destroy_scope_allowing_leaks()` ~~~c void (*destroy_scope_allowing_leaks)(uint32_t scope, uint64_t max_leaked_bytes); ~~~ As `destroy_scope()` 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. #### `record_realloc()` ~~~c 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. #### `allocated_bytes()` ~~~c uint64_t (*allocated_bytes)(const uint32_t scope); ~~~ Returns the total number of bytes currently allocated in the specified scope. #### `allocation_count()` ~~~c uint64_t (*allocation_count)(const uint32_t scope); ~~~ Returns the total number of allocations in the specified scope. #### `set_scope_tracing()` ~~~c 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.` #### `scope_data_snapshot()` ~~~c /* 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). #### `trace_data_snapshot()` ~~~c /* 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`.
### `tm_memory_tracker_api_version`
~~~c #define tm_memory_tracker_api_version ~~~