![]() |
CRM64Pro GDK v0.18.0
A free cross-platform game development kit built on top of SDL 3.0
|
High-performance and thread-safe memory allocation system [v26.02.0].
The CRM64Pro Memory Manager (CMem) provides high-performance, thread-safe functions for allocating memory blocks while helping to reduce memory fragmentation. All CRM64Pro GDK modules and external libraries (SDL3, libpng, etc.) use CMem for memory allocation and deallocation.
Client applications can also use CMem and define different module numbers for precise and specific statistics tracking.
CMem is composed of three different functional layers:
| Frontend | User-facing API: alloc(), calloc(), realloc(), allocAligned(), free(), freeAligned(), setStatsLevel(), setVerboseSampleInterval(), info() and destroy() |
|---|---|
| Stats system | Per-module memory tracking, CSV profiling, and logging bridge |
| Low-level allocator | Pluggable backend allocator (Standard C/C++ or ltalloc) |
CMem utilizes a Single pipe architecture for outputting statistics:
CMem::destroy() at the very end of main()), CMem automatically falls back to the last known log configuration (File/Console) to ensure final leak reports are not lost. The stats system provides memory information for each of the following modules:
| CRM64Pro | Modules, managers, objects, STL containers and network system |
|---|---|
| Core libraries | SDL3, TinyXML2 and zlib-ng |
| Audio libraries | libxmp, dr-flac, dr-mp3 and stb-vorbis |
| Image libraries | libpng |
| User modules | Custom modules (IDs 16-31) defined by the client application via setModuleName() |
In ::MSL_VERBOSE mode, two CSV files are produced:
| Allocation histogram | Distribution of all allocation sizes grouped by module |
|---|---|
| Memory evolution | Time-series snapshots of memory allocation per module (default interval: 0.5 seconds, configurable via setVerboseSampleInterval()) |
Two allocator backends are available. The selection affects how exact memory usage is tracked on different platforms:
| Standard C/C++ | Default system allocator. Windows: Uses _msize for exact tracking. Linux: Uses malloc_usable_size. macOS: Uses malloc_size. |
|---|---|
| ltalloc | Modified high-performance allocator. Cross-platform exact tracking via ltmsize. Thread-safe with some memory overhead (see details below) |
ltalloc details
The ltalloc allocator requests memory from the operating system in 1MB blocks and automatically creates memory pools for common allocation sizes:
<h3>Best practices</h3>
<ul>
<li>Call setStatsLevel() before any other CMem function in your main() to capture all allocation information.</li>
<li>The stats gathering level can be modified at any point, but info() will dump based on the current active mode.</li>
<li>Call destroy() at the very end of your application (or via <code>atexit</code>) to generate the final report.</li>
<li><b>Context Aware Reporting:</b> The final report automatically distinguishes between actual leaks and "pending" deletions from global/static STL objects.</li>
</ul>
<h3>CMemAllocator allocation rule</h3>
CRM64Pro is exception-free for engine object allocation. Classes derived from <code>CMemAllocator</code>
must be dynamically allocated with <code>new(std::nothrow)</code> and the returned pointer must be checked
against <code>nullptr</code>. Plain <code>new</code> and <code>new[]</code> are intentionally disabled for these
classes, so allocation failures are handled through explicit checks and the normal CRM64Pro error-code flow.
Deallocate objects normally with <code>delete</code> or <code>delete[]</code>.
<br><br>
Example:<br>
<code>SceneObject* pObj = new(std::nothrow) MySceneObject();<br>
if(!pObj) return nullptr;</code>
@note CRM64Pro STL containers use the CMem allocator and are not directly compatible with standard STL containers.
Explicit conversions are required:<br>
CRM64Pro::string sSource = "sourceValue";
std::string sDest = sSource; // Will fail
std::string sDest = sSource.c_str(); // OK
C64_OVERRIDE_NEW before including the headers and compiling CRM64Pro GDK. If enabled, all C++ allocations will be tracked by CMem.Enumerations | |
| enum | CRM64Pro::CMem::eMemStatsLevel : Sint32 { CRM64Pro::CMem::MSL_NULL = 0 , CRM64Pro::CMem::MSL_NORMAL = 2 , CRM64Pro::CMem::MSL_HIGH = 4 , CRM64Pro::CMem::MSL_VERBOSE = 8 , CRM64Pro::CMem::MSL_DEBUG = 16 } |
| Memory statistics verbosity. More... | |
Functions | |
| Sint32 | CRM64Pro::CMem::setModuleName (eMemoryModule eMM, const char *szName) |
| Set the name for a custom user module. | |
| void | CRM64Pro::CMem::setVerboseSampleInterval (Sint32 iInterval) |
| Set time interval between each sample when the stats level is ::MSL_VERBOSE. By default it is set to 500ms. | |
| void | CRM64Pro::CMem::setStatsLevel (eMemStatsLevel eMSL) |
| Set the memory stats gathering level. | |
| void | CRM64Pro::CMem::setBreakOnAlloc (Uint32 iAllocID) |
| Set the Allocation ID to break on. | |
| void * | CRM64Pro::CMem::alloc (size_t iSize, eMemoryModule eMM=CMM_C64) |
| Reserve a memory block using CMem. | |
| void * | CRM64Pro::CMem::calloc (size_t iNum, size_t iSize, eMemoryModule eMM=CMM_C64) |
| Reserve a memory block using CMem and reset it to 0. | |
| void * | CRM64Pro::CMem::realloc (void *pMem, size_t iSize, eMemoryModule eMM=CMM_C64) |
| Reallocate a memory block using CMem. | |
| void * | CRM64Pro::CMem::allocAligned (size_t iSize, size_t iAlign=CRM64PRO_CMEM_ALIGNMENT, eMemoryModule eMM=CMM_C64) |
| Reserve a memory block using CMem aligned to the desired value. | |
| void | CRM64Pro::CMem::free (void *pMem) |
| Deallocate a memory block using CMem. | |
| void | CRM64Pro::CMem::freeAligned (void *pMem) |
| Deallocate a memory block using CMem. | |
| void | CRM64Pro::CMem::destroy () |
| Releases the internal heap and displays final stats. | |
| Sint32 | CRM64Pro::CMem::info (Sint32 iMode=1) |
| Output useful information about the memory usage. | |
| enum CRM64Pro::CMem::eMemStatsLevel : Sint32 |
Memory statistics verbosity.
| Enumerator | |
|---|---|
| MSL_NULL | Disable memory statistics gathering. Default for release builds. |
| MSL_NORMAL | Collect allocations per module (CRM64Pro and user). Default for debug builds. |
| MSL_HIGH | ::MSL_NORMAL plus deallocations and sizes logging for each module. |
| MSL_VERBOSE | ::MSL_HIGH plus: memory growth per module (CMem-Evolution.csv) and size histogram per module (CMem-Histogram.csv). |
| MSL_DEBUG | ::MSL_VERBOSE plus: Allocation ID tracking and memory dump for leak detection. Use setBreakOnAlloc() to catch specific leaks. [Debug builds only] |
| CRM64PRO_API Sint32 CRM64Pro::CMem::setModuleName | ( | eMemoryModule | eMM, |
| const char * | szName ) |
Set the name for a custom user module.
| eMM | ID of the user module. Must be in the range [CMM_USER_START, CMM_USER_END] (16 to 31). |
| szName | Name of the custom user module. Maximum 31 characters; longer names are truncated. By default, all custom user modules are shown as "User". |
| CRM64PRO_API void CRM64Pro::CMem::setVerboseSampleInterval | ( | Sint32 | iInterval | ) |
Set time interval between each sample when the stats level is ::MSL_VERBOSE. By default it is set to 500ms.
| iInterval | integer with time in milliseconds [1, 30000]. |
| CRM64PRO_API void CRM64Pro::CMem::setStatsLevel | ( | eMemStatsLevel | eMSL | ) |
Set the memory stats gathering level.
| eMSL | Stats gathering level. See ::eMemStatsLevel for details. |
| CRM64PRO_API void CRM64Pro::CMem::setBreakOnAlloc | ( | Uint32 | iAllocID | ) |
Set the Allocation ID to break on.
When the internal allocation counter matches this ID, a debugger breakpoint is triggered. Useful for tracking down the source of a specific memory leak identified by its AllocID in the MSL_DEBUG report.
| iAllocID | The allocation ID to break on. 0 to disable (default). |
| CRM64PRO_API void * CRM64Pro::CMem::alloc | ( | size_t | iSize, |
| eMemoryModule | eMM = CMM_C64 ) |
Reserve a memory block using CMem.
It is automatically aligned to 16 bytes.
| iSize | size of the memory block, in bytes. |
| eMM | used for storing who requested the memory for statistics results. Internal modules use [0-15]. User modules must be in range [CMM_USER_START, CMM_USER_END] (16-31). |
| CRM64PRO_API void * CRM64Pro::CMem::calloc | ( | size_t | iNum, |
| size_t | iSize, | ||
| eMemoryModule | eMM = CMM_C64 ) |
Reserve a memory block using CMem and reset it to 0.
It is automatically aligned to 16 bytes.
| iNum | number of elements to allocate. |
| iSize | size of each element. |
| eMM | used for storing who requested the memory for statistics results. Internal modules use [0-15]. User modules must be in range [CMM_USER_START, CMM_USER_END] (16-31). |
| CRM64PRO_API void * CRM64Pro::CMem::realloc | ( | void * | pMem, |
| size_t | iSize, | ||
| eMemoryModule | eMM = CMM_C64 ) |
Reallocate a memory block using CMem.
It is automatically aligned to 16 bytes.
| pMem | pointer to the memory area to be reallocated. |
| iSize | size of the memory block, in bytes. |
| eMM | used for storing who requested the memory for statistics results. Internal modules use [0-15]. User modules must be in range [CMM_USER_START, CMM_USER_END] (16-31). |
| CRM64PRO_API void * CRM64Pro::CMem::allocAligned | ( | size_t | iSize, |
| size_t | iAlign = CRM64PRO_CMEM_ALIGNMENT, | ||
| eMemoryModule | eMM = CMM_C64 ) |
Reserve a memory block using CMem aligned to the desired value.
| iSize | size of the memory block, in bytes. |
| iAlign | specifies the alignment. Must be a valid alignment supported by the implementation. Usually a 2^n number is supported. |
| eMM | used for storing who requested the memory for statistics results. Internal modules use [0-15]. User modules must be in range [CMM_USER_START, CMM_USER_END] (16-31). |
| CRM64PRO_API void CRM64Pro::CMem::free | ( | void * | pMem | ) |
| CRM64PRO_API void CRM64Pro::CMem::freeAligned | ( | void * | pMem | ) |
Deallocate a memory block using CMem.
| pMem | pointer to a memory block previously allocated with allocAligned(). |
| CRM64PRO_API void CRM64Pro::CMem::destroy | ( | ) |
Releases the internal heap and displays final stats.
| CRM64PRO_API Sint32 CRM64Pro::CMem::info | ( | Sint32 | iMode = 1 | ) |
Output useful information about the memory usage.
| iMode | 1 for displaying extra information about the Low-level allocator (default value) or 0 for disabling it. |