Skip to content

Switch GLFWGamepadState use to fix double free in ImGuiImplGlfw - #440

Open
Lunafina wants to merge 1 commit into
SpaiR:mainfrom
Lunafina:fix/gamepad_state_invalid_memory_management
Open

Lunafina wants to merge 1 commit into
SpaiR:mainfrom
Lunafina:fix/gamepad_state_invalid_memory_management

Conversation

@Lunafina

@Lunafina Lunafina commented Oct 1, 2026 •

Copy link
Copy Markdown
  • GLFWGamepadState creation with .create() creates a java native ByteBuffer backing the GLFWGamepadState. The GLFWGamepadState's .close() uses the NativeResource .close() default implementation, that calls .free(). Which, at some point, causes a crash from trying to free a java natively allocated object. That manifests as a double free.
  • As a fix, either using .create() with no .close(), letting the JVM handle the gamepad state, or using .malloc() with .close() or .free(), handling the cpp native memory manually.

Summary

Replace the try-with-resource statement handling GLFWGamepadState in ImGuiImplGlfw causing a memory related crash after a certain time. The crash can be reproduced by using GLFW + OpenGL (3.3+), and setting the config flag NavEnableGamepad and using repeatedly the ImGuiImplGlfw .newFrame() method:

        for (int idx = 0; idx < 100000; idx++) {
            this.imGuiGL3.newFrame();
            this.imGuiGLFW.newFrame();
            ImGui.newFrame();
            ImGui.render();
            this.imGuiGL3.renderDrawData(ImGui.getDrawData());

            glfwSwapBuffers(this.glfwWindow);
        }
        this.imGuiGL3.shutdown();
        this.imGuiGLFW.shutdown();
        ImGui.destroyContext();

Type of change

  • Minor changes or tweaks (quality of life stuff)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Notes for reviewer

The memory related crash seems to come from the fact that the gamepad object storing the gamepad state is handled by a try-with-resource statement automatically calling the .close() method of the object. This method is using the default implementation of the NativeResource interface, which calls .free(), releasing the allocator allocated address. But, the gamepad is actually created using .create() which uses java native object creation. Thus, the .close() is trying to free a java allocated address, causing the crash.

There are two possible fixes, either gamepad can be created with .malloc(), the memory would then be allocated and freed the C++ way, or the try-with-resource statement can be removed to simply use the java native object the java way, letting the JVM clean the memory.

I opted to fix this issue by staying in Java, thus removing the try-with-resource statement.

In the investigation process of this memory related crash, having only double free in tcache2 as clue, I used Claude Haiku 4.5 when I was out of idea. It redirected me to look at the other part of the code, such as the gamepad code. Thus, it helped me to locate the bug but did not write any code. So I don't know if it should be acknowledged as co-author. Let me know if it should not.

@Lunafina Lunafina changed the title Switch GLFWGamepadState use to fix double free in imguiGlfwImpl Switch GLFWGamepadState use to fix double free in ImGuiImplGlfw Oct 2, 2026
* GLFWGamepadState creation with `.create()` creates a java native
ByteBuffer backing the GLFWGamepadState. The GLFWGamepadState's
`.close()` uses the NativeResource `.close()` default implementation,
that calls `.free()`. Which, at some point, causes a crash from
trying to free a java natively allocated object. That manifests as
a double free.
* As a fix, either using `.create()` with no `.close()`, letting the
JVM handle the gamepad state, or using `.malloc()` with `.close()` or
`.free()`, handling the cpp native memory manually.

Co-authored-by: Claude <noreply@anthropic.com>
@Lunafina
Lunafina force-pushed the fix/gamepad_state_invalid_memory_management branch from 6d24ddf to ddb4643 Compare October 2, 2026 13:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant