Memory Allocations¶
Blender features its own memory allocation library, which is a thin wrapper around an underlying allocator. Depending on the platform and type of build, this allocator can be the oneTBB allocator, or the system allocator. Previously the jemalloc library was used as well.
Its API is defined in
intern/guardedalloc/MEM_guardedalloc.h.
MEM API¶
MEM provides C++ template versions of the new/delete operators (MEM_new and MEM_delete),
which are the preferred way to create and delete data in new code.
Note
Technically, MEM_delete is a template (MEM_delete<T>). However,
compilers should always be able to deduct the correct type from the given
parameter, so it should never be needed to explicitly specify that
template parameter:
Uninitialized and Zeroed¶
MEM also provides MEM_new_uninitialized and MEM_new_zeroed functions that behave like malloc
and calloc respectively. Compared to the native C functions, these provide improved type safety,
ensure that the allocated types are trivial, and reduce the casting verbosity by directly returning
a pointer of the expected type. This memory should be freed with MEM_delete.
There are a few reasons to use these functions rather than MEM_new:
- Performance: When allocating large arrays like image buffers or mesh attributes that will be initialized soon after, doing an uninitialized memory allocation is faster.
- Low level code: Core data structures and other low level code that directly allocate a raw buffer of bytes and provide their own type safety.
- Legacy: Code that has not yet been updated to follow current conventions.
Arrays¶
Whenever possible, arrays should be allocated with Vector and similar high level data types.
The main reasons to allocate arrays directly are DNA data and interacting with legacy code.
For arrays there is MEM_new_array with variations for uninitialized, zeroed and aligned memory.
This can only be used for trivially destructible types. For this reason it also works with
MEM_delete, and there is no equivalent of delete [].
Duplication and Reallocation¶
There are convenience functions MEM_dupalloc and MEM_realloc to duplicate or change the
size of an allocation. These can only be used with trivially destructible types.
These exist mainly for legacy reasons, and when possible MEM_new should be used for copying
a single allocation, while Vector should be used for arrays.
Void Pointers¶
Freeing and duplicating void pointers must be done with MEM_delete_void and MEM_dupalloc_void.
These functions mainly exist for legacy reasons, for example in code to attach an arbitrary void
userdata pointer to a callback function pointer. In these cases it must be carefully checked that
the type is trivially destructible.
They may be used for low level data structures, but other usage should be eliminated over time.
Standard new & delete Operators¶
Using the new and delete operators for Blender data types should
typically be avoided.
However, there are some cases where this is difficult not to use them
(e.g. when using external libraries or the standard containers, like
std::vector).
In such cases, it is still possible to get default new/delete operators
to use the MEM_guardedalloc allocator, by overloading them in the
affected data types. Structs and classes that need this should use the
MEM_CXX_CLASS_ALLOC_FUNCS macro in their declaration.
Note that a type using overloaded new & delete operators can still also
be created and deleted with MEM_new<T> and MEM_delete<T>.
Memory Debugging¶
MEM provides guarded memory management when using the --debug-memory option. All allocated
memory is then enclosed by pads, to detect out-of-bound writes. All allocations are named
to detect the source of memory leaks and print memory usage at runtime with the
"Memory Statistics" operator.