Custom ImGui Memory Allocator Configuration for Engines

Dear ImGui allows complete replacement of its internal memory allocation functions via ImGui::SetAllocatorFunctions(), enabling game engines to route all ImGui heap operations through custom memory pools, trackers, or aligned allocators.

Game engines integrating the popular immediate-mode GUI library Dear ImGui (ocornut/imgui) often require tight control over memory allocation for profiling, alignment constraints, or platform-specific heap requirements. The library exposes a clean C-style callback mechanism to override its default malloc/free usage without modifying core source files.

Understanding ImGui's Allocation Architecture

Dear ImGui abstracts allocation through two function pointer types defined in imgui.h at lines 288-289: ImGuiMemAllocFunc and ImGuiMemFreeFunc. These define the required signatures for custom allocation (void* (*)(size_t, void*)) and deallocation (void (*)(void*, void*)), respectively.

Default Allocators and Configuration

By default, ImGui uses standard malloc and free. You can force the library to exclude these defaults entirely by defining IMGUI_DISABLE_DEFAULT_ALLOCATORS in your imconfig.h (or via compiler flags), as documented in imconfig.h lines 52-53. When this macro is defined, you must supply custom functions before creating any context, or the application will fail to link.

Per-Context Storage

Each ImGuiContext stores its own allocator pointers, permitting multiple simultaneous contexts to use different memory strategies. As implemented in imgui.cpp, the allocator functions are stored at the context level, meaning you can isolate ImGui memory usage per subsystem if needed.

Implementing Custom Allocators in Your Engine

To integrate your engine's memory manager with ImGui, follow this sequence precisely:

  1. Implement the callback functions matching the ImGuiMemAllocFunc and ImGuiMemFreeFunc signatures.
  2. Optionally disable defaults by defining IMGUI_DISABLE_DEFAULT_ALLOCATORS to prevent ImGui from linking against CRT heap functions.
  3. Install the allocator by calling ImGui::SetAllocatorFunctions() before ImGui::CreateContext()—this is a hard requirement documented in imgui.h line 1158.
  4. Create the context, which will now route all internal allocations through your supplied functions.

DLL Boundary Considerations

When compiling ImGui into a dynamic library (DLL), the heap is not shared across DLL boundaries. Every DLL that uses ImGui must call both SetCurrentContext() and SetAllocatorFunctions() to maintain consistent allocator state, as noted in imconfig.h lines 25-26. Failure to do so will result in memory being freed through a different allocator than allocated it, causing immediate heap corruption.

Complete Integration Example

The following pattern demonstrates forwarding allocations to an engine's pool allocator:

// EngineMemory.h
struct EngineMemory {
    void* allocate(size_t size) { return myPool->alloc(size); }
    void  deallocate(void* ptr) { myPool->free(ptr); }
};

// ImGui allocator callbacks
static void* MyImGuiAlloc(size_t sz, void* user_data)
{
    return static_cast<EngineMemory*>(user_data)->allocate(sz);
}

static void MyImGuiFree(void* ptr, void* user_data)
{
    static_cast<EngineMemory*>(user_data)->deallocate(ptr);
}

// ---------------------------------------------------------------------
// Engine initialization - must run before any ImGui context creation
EngineMemory gEngineMemory;

void InitImGui()
{
    // Optionally ensure defaults are disabled in your imconfig.h:
    // #define IMGUI_DISABLE_DEFAULT_ALLOCATORS
    
    ImGui::SetAllocatorFunctions(MyImGuiAlloc, MyImGuiFree, &gEngineMemory);
    ImGui::CreateContext();  // Now uses custom allocator exclusively
}

For frame-based allocation strategies (such as linear "scratch" allocators), you can implement MyImGuiAlloc to obtain memory from the current frame's buffer and leave MyImGuiFree as a no-op, since ImGui automatically releases all memory when the context is destroyed.

Summary

  • Hook early: Always call ImGui::SetAllocatorFunctions() before ImGui::CreateContext() when using custom allocators.
  • Type safety: Implement callbacks matching ImGuiMemAllocFunc (void* (*)(size_t, void*)) and ImGuiMemFreeFunc (void (*)(void*, void*)).
  • Configuration: Define IMGUI_DISABLE_DEFAULT_ALLOCATORS in imconfig.h to strip default malloc/free dependencies.
  • DLL safety: Re-install allocators in every DLL boundary using SetAllocatorFunctions() alongside SetCurrentContext().
  • Debug visibility: Reference imgui.cpp and imgui_internal.h for internal context storage details when debugging allocator usage.

Frequently Asked Questions

When exactly must I call SetAllocatorFunctions?

You must call ImGui::SetAllocatorFunctions() before the first invocation of ImGui::CreateContext(). According to the source code in imgui.h line 1158, the allocator is captured during context creation and cannot be changed for an active context without destroying and recreating it.

Can different ImGui contexts use different allocators?

Yes. Because ImGuiContext stores its own allocator function pointers as implemented in imgui.cpp, you can create multiple contexts each with distinct allocators by calling SetAllocatorFunctions() before each CreateContext() call. This enables per-subsystem memory isolation.

What happens if I disable default allocators but forget to set custom ones?

If you define IMGUI_DISABLE_DEFAULT_ALLOCATORS in imconfig.h (lines 52-53) but fail to provide replacement functions, your build will fail at link time due to unresolved malloc/free symbols. The macro completely removes the default implementations from the compiled library.

How do I handle SIMD alignment requirements in my custom allocator?

Your ImGuiMemAllocFunc implementation must return memory aligned to the requirements of your target platform (typically 16-byte for SSE or 32-byte for AVX). ImGui itself does not impose alignment requirements beyond standard C++ object alignment, but passing insufficiently aligned memory to ImGui functions that later feed into graphics APIs may cause crashes during vertex buffer uploads.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →