From ddb4643776ee87bef0bf2bec48c1dac04445669e Mon Sep 17 00:00:00 2001 From: lunafina Date: Thu, 1 Oct 2026 18:35:07 +0200 Subject: [PATCH] fix(lwjgl3): switch GLFWGamepadState memory strategy to fix double free * 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 --- .../main/java/imgui/glfw/ImGuiImplGlfw.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/imgui-lwjgl3/src/main/java/imgui/glfw/ImGuiImplGlfw.java b/imgui-lwjgl3/src/main/java/imgui/glfw/ImGuiImplGlfw.java index 31db5e34..445b6e11 100644 --- a/imgui-lwjgl3/src/main/java/imgui/glfw/ImGuiImplGlfw.java +++ b/imgui-lwjgl3/src/main/java/imgui/glfw/ImGuiImplGlfw.java @@ -1143,17 +1143,16 @@ protected void updateGamepads() { final MapAnalog mapAnalog; if (glfwHasGamepadApi) { - try (GLFWGamepadState gamepad = GLFWGamepadState.create()) { - if (!glfwGetGamepadState(GLFW_JOYSTICK_1, gamepad)) { - return; - } - mapButton = (keyNo, buttonNo, _unused) -> io.addKeyEvent(keyNo, gamepad.buttons(buttonNo) != 0); - mapAnalog = (keyNo, axisNo, _unused, v0, v1) -> { - float v = gamepad.axes(axisNo); - v = (v - v0) / (v1 - v0); - io.addKeyAnalogEvent(keyNo, v > 0.10f, saturate(v)); - }; + GLFWGamepadState gamepad = GLFWGamepadState.create(); + if (!glfwGetGamepadState(GLFW_JOYSTICK_1, gamepad)) { + return; } + mapButton = (keyNo, buttonNo, _unused) -> io.addKeyEvent(keyNo, gamepad.buttons(buttonNo) != 0); + mapAnalog = (keyNo, axisNo, _unused, v0, v1) -> { + float v = gamepad.axes(axisNo); + v = (v - v0) / (v1 - v0); + io.addKeyAnalogEvent(keyNo, v > 0.10f, saturate(v)); + }; } else { final FloatBuffer axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1); final ByteBuffer buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1);