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 jemalloc library, the oneTBB allocator, or the default system one.

Its API is defined in intern/guardedalloc/MEM_guardedalloc.h.

C++-style Creation - MEM_new and MEM_delete

The main way to allocate and construct an instance of a type in C++ code is to use the MEM_new<T> template function. It will allocate memory for the given type and call its constructor.

Just like when using the new operator, parameters for the constructor can be passed to the MEM_new<T> function.

Note

Even when creating 'C' data (i.e. using trivial data types), in new C++ code it is recommended to use this API whenever possible. This will save a fair amount of work (and potential issues) if/when said types become non-trivial in the future.

Data allocated and constructed this way must be destructed and freed with MEM_delete.

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 explicitely specify that template parameter:

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

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>.

C-style Allocation - MEM_[cm]allocN & MEM_freeN

In C++ code, when using MEM_new<T>/MEM_delete<T> is not possible, the recommended way to allocate memory for a given struct (without any construction) is to use the templated version of MEM_callocN<T>/ MEM_mallocN<T> (or MEM_calloc_arrayN<T>/ MEM_malloc_arrayN<T> for arrays). This is essentially a template wrapper around calloc/malloc, i.e. it will allocate the requested memory for the given type (and initialize it to zero for the calloc ones).

This API is type-safe, in that it ensures that the allocated type matches the returned pointer type. It also does some basic checks at compile time, ensuring that the given type is 'trivial', i.e. that it does not require any constructor call to be valid. This adds a significant amount of safety in a codebase that mixes heavily trivial, C-style data types (also known as POD, Plain Old Data), with non-trivial, C++-style ones.

The main reason to use this allocation-only API in new code is in case the created data needs to be used in some existing code, that manages it with 'C-style' allocation calls.

The historic API (non-templated, type-agnostic MEM_mallocN, MEM_callocN, etc.) should only be used directly in specific cases. In general, when a specific allocation size value has to be used: * When allocating a not fully defined type, or some raw buffer of bytes. * In implementation of some containers (like Vector or Map), when calling code explicitely needs to allocate memory for a non-trivial C++ struct, and take care of its construction (e.g. with a placement new) separately. * In some Blender historic core code, mimicking C++ type inheritance, e.g. ID and Modifier creation.

Data allocated these ways (both the templated and 'C-style' versions of the API) must be freed with MEM_freeN. This function also does static type checking regarding triviality of the deleted data type, in C++ code. In case the type is not fully defined when freeing the data: * It might be worth reconsidering the API around that type (as it likely means that it is allocated somewhere, and freed in a completely different part of the code). * If such 'unknown data' freeing is really necessary, the pointer must be explicitly cast to void * in the call to MEM_freeN.

Note

Technically, as with MEM_delete, MEM_freeN is a template (MEM_freeN<T>), but explicitely giving the type parameter to the template should never be needed.

Note

The C-compatible version of MEM_freeN, which takes a void * parameter, is implemented as a non-templated overload of the function.