Skip to content

ImGuiIntegration memory corruption when destroying context with custom font loaded via AddFontFromMemoryTTF #42

Description

@matusnovak

The problem

I apologise if this is not MagnumImGuiIntegration problem but ImGui problem instead. I am not sure what is the exact cause of this problem so I have started here.

I am following the ImGui example from here: https://doc.magnum.graphics/magnum/examples-imgui.html

I am trying to load a custom font from a ttf file. Had to slightly modify the original example below into the following:

IMGUI_CHECKVERSION();
context = ImGui::CreateContext();

const Utility::Resource rs{ "fonts" };
const auto ttfRaw = rs.getRaw(<font name here>);
ImGuiIO& io = ImGui::GetIO();
imguiFont = io.Fonts->AddFontFromMemoryTTF(reinterpret_cast<void*>(const_cast<char*>(ttfRaw.data())), ttfRaw.size(), 18.0f);
IM_ASSERT(imguiFont != NULL);
io.Fonts->Build();

// Passing ImGui context into the constructor!
_imgui = ImGuiIntegration::Context(*context, Vector2{windowSize()}/dpiScaling(), windowSize(), framebufferSize());

I am able to draw the ImGui with the custom font without issues. However when the _imgui falls out of scope (on program exit), ImGui tries to delete invalid memory.

The exact traceback:

MagnumImGuiIntegration-d.dll!FreeWrapper(void * ptr, void * user_data) Line 1065
MagnumImGuiIntegration-d.dll!ImGui::MemFree(void * ptr) Line 2966
MagnumImGuiIntegration-d.dll!ImFontAtlas::ClearInputData() Line 1462
MagnumImGuiIntegration-d.dll!ImFontAtlas::Clear() Line 1500
MagnumImGuiIntegration-d.dll!ImFontAtlas::~ImFontAtlas() Line 1452
[External Code]	
MagnumImGuiIntegration-d.dll!IM_DELETE<ImFontAtlas>(ImFontAtlas * p) Line 1534
MagnumImGuiIntegration-d.dll!ImGui::Shutdown(ImGuiContext * context) Line 3570
MagnumImGuiIntegration-d.dll!ImGui::DestroyContext(ImGuiContext * ctx) Line 3035
MagnumImGuiIntegration-d.dll!Magnum::ImGuiIntegration::Context::~Context() Line 137
magnum-imgui.exe::ImGuiExample::~ImGuiExample()

Inside of the FreeWrapper it is trying to call free(); with pointer that comes from my exe. (Visual Studio reports that the address of the pointer belongs to the exe, not to the Magnum DLL.)

Workaround

It seems that if I add io.Fonts->ConfigData.clear(); before creating ImGuiIntegration::Context it works without issues. So I get the following:

ImGuiIO& io = ImGui::GetIO();
imguiFont = io.Fonts->AddFontFromMemoryTTF(reinterpret_cast<void*>(const_cast<char*>(ttfRaw.data())), ttfRaw.size(), 18.0f);
IM_ASSERT(imguiFont != NULL);
io.Fonts->Build();
io.Fonts->ConfigData.clear();

No memory corruption on exit. But why?

Additional info

OS: Windows 10
Compiler: Visual Studio 15 2017 Win64 (14.16.27023)
Configuration: Debug
Magnum integration version: Commit 31ccefc
ImGui version: Commit ocornut/imgui@79f7778
Haven't tried Linux or OSX

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions