LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Edde on September 28, 2020, 16:43:36

Title: Assimp memory leak
Post by: Edde on September 28, 2020, 16:43:36
I'm trying to load obj models using assimp but I get a memory leak

[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3EE50000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileCloseProc.<init>(AIFileCloseProc.java:51)
   at com.eldev.engine.loader.MeshLoader$2.<init>(MeshLoader.java:80)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:80)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3EE40000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileOpenProc.<init>(AIFileOpenProc.java:52)
   at com.eldev.engine.loader.MeshLoader$1.<init>(MeshLoader.java:40)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:40)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D40490000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
   at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D404B0000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
   at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D404A0000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
   at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5D0000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
   at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5C0000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
   at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3F5B0000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
   at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD40000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileTellProc.<init>(AIFileTellProc.java:50)
   at com.eldev.engine.loader.MeshLoader$1$3.<init>(MeshLoader.java:69)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:69)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD30000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileSeek.<init>(AIFileSeek.java:52)
   at com.eldev.engine.loader.MeshLoader$1$2.<init>(MeshLoader.java:57)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:57)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
[LWJGL] 16 bytes leaked, thread 1 (Game Thread), address: 0x12D3FD20000
   at org.lwjgl.system.Callback.create(Callback.java:136)
   at org.lwjgl.system.Callback.<init>(Callback.java:86)
   at org.lwjgl.assimp.AIFileReadProc.<init>(AIFileReadProc.java:53)
   at com.eldev.engine.loader.MeshLoader$1$1.<init>(MeshLoader.java:50)
   at com.eldev.engine.loader.MeshLoader$1.invoke(MeshLoader.java:50)
   at org.lwjgl.assimp.AIFileOpenProcI.callback(AIFileOpenProcI.java:33)
   at org.lwjgl.system.JNI.invokePPP(Native Method)
   at org.lwjgl.assimp.Assimp.naiImportFileEx(Assimp.java:2593)
   at org.lwjgl.assimp.Assimp.aiImportFileEx(Assimp.java:2641)
   at com.eldev.engine.loader.MeshLoader.loadMesh(MeshLoader.java:86)
   at com.eldev.game.Game.main(Game.java:26)
Title: Re: Assimp memory leak
Post by: spasi on September 29, 2020, 13:45:31
LWJGL callback function objects must be manually freed to avoid memory leaks.
Title: Re: Assimp memory leak
Post by: Edde on September 29, 2020, 18:49:35
When I free the callback function objects i get an exception

Exception in thread "Render Thread" java.lang.IllegalStateException: The memory address specified is not being tracked: 0x15D01D9A4F0
at org.lwjgl.system.MemoryManage$DebugAllocator.untrack(MemoryManage.java:259)
at org.lwjgl.system.MemoryManage$DebugAllocator.free(MemoryManage.java:220)
at org.lwjgl.system.MemoryUtil.nmemFree(MemoryUtil.java:336)
Title: Re: Assimp memory leak
Post by: spasi on September 29, 2020, 19:10:25
Which LWJGL version do you use?
Title: Re: Assimp memory leak
Post by: Edde on September 29, 2020, 19:32:05
LWJGL 3.2.3 Build 13
Title: Re: Assimp memory leak
Post by: spasi on September 30, 2020, 15:34:37
I think the issue is that AIFileIO's OpenProc and CloseProc are invoked multiple times (3 in my testing) within a single aiImportFileEx call. If OpenProc creates a new AIFile each time, then you need to make sure that the corresponding CloseProc invocation is freeing those callbacks.

This is a bit wasteful of course. Depending on how your code is structured, you may be able to reuse the callback instances and avoid the overhead.
Title: Re: Assimp memory leak
Post by: Edde on September 30, 2020, 19:00:48
I got the same memory leak when I tested this demo
https://github.com/LWJGL/lwjgl3-demos/blob/main/src/org/lwjgl/demo/opengl/assimp/WavefrontObjDemo.java
Title: Re: Assimp memory leak
Post by: spasi on October 03, 2020, 18:00:12
WavefrontObjDemo has been fixed (https://github.com/LWJGL/lwjgl3-demos/commit/1b31a5f7b9e48ca8531445b3921a30c3fe3e611e) to properly cleanup the AIFileIO & AIFile callbacks.