Skip to content

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:

MyClass *var = MEM_new<MyClass>(__func__);
MEM_delete(var);

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.