Dealing with Allocator Mismatches when using external Libraries
Unreal Engine uses its own allocators, a.k.a. new()
/delete()
implementation, such as mallocbinned2
. Deleting memory that has been allocated outside of Unreal (e.g. from a library/DLL that uses standard new/delete implementations) through Unreal’s allocator will usually result in crashes. The same is true for the opposite, when memory that comes from Unreal’s allocator is being passed to a library that uses the standard allocator to free it.
This issue can often manifest itself when using standard library classes like std::string
or passing these through DLL boundaries, e.g. a library function that returns a std::string
object.
Example Error messages:
FMallocBinned2 Attempt to realloc an unrecognized block 000002025F080000 canary == 0x0 != 0xe3
malloc: *** error for object 0x3140000009c5b: pointer being free was not allocated
Usually the call stack will contain some library code and then go through one of the FMemory::Malloc()/Free()/Realloc()
calls of the Engine API.
To validate whether this is the case the engine can be started with the “-ansimalloc” flag. This will disable all custom allocators and use the new/delete functions of the standard library.
How to deal with Allocator Mismatches
There are a few possible solutions/workarounds for dealing with allocator mismatches.
Libraries with Custom Allocator support
Some libraries have an API to provide custom allocator functions, making it possible to supply a user-defined function for new()/delete()
or Malloc()/Free()
calls.
These can be used to let a library use Unreal’s memory functions, which can be found in the FMemory class in UnrealMemory.h:
FMemory::Malloc()
FMemory::Realloc()
FMemory::Free()
Since Unreal Engine 5.3 each module will also have the following local functions defined that can be used instead of referencing FMemory
directly, see ModuleBoilerPlate.h:
void* StdMalloc( size_t Size, size_t Alignment );
void* StdRealloc( void* Original, size_t Size, size_t Alignment );
void StdFree( void *Ptr );
Static Linking
Unreal does overload C++'s new()
and delete()
operators to forward allocations to the FMemory
API.
This only works for code compiled through Unreal’s build environment.
If you are using a dynamic library (.dll
) and you have the option of linking this library statically instead (e.g. only a .lib) then the linker should replace the libraries allocations with Unreal’s new()
/delete()
hooks.
Using the default/standard Allocator
Starting Unreal with the -ansimalloc
parameter can be used as a last resort if no other workarounds are applicable. This is not recommended, since Unreal’s build-in allocators usually have better performance at runtime.