Description
Issue description
I was noticing some memory leaks that happen while loading / unloading models repeatedly.
I decided to investigate this issue and made a minimal reproduction of this bug (seen at the bottom of this issue). Increasing the iteration count in that code example proportionally leads to alarger maximum resident set. I compiled raylib with symbols and ran that example through asan, according to which the leak is from an allocation in line 5737 in rmodels.c
:
if (attribute->component_type == cgltf_component_type_r_8u)
{
// Init raylib mesh color to copy glTF attribute data
=> model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char)); // !! OFFENDING LINE !!
// Load 4 components of unsigned char data type into mesh.colors
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
}
else if (attribute->component_type == cgltf_component_type_r_16u)
The memory leak seems to happen in relation to vertex color data.
Another fact that speaks to this is that the bug is not present when loading a .glb of a plain blender default cube, but memory starts being leaked as soon as it's exported with some vertex colors applied from the vertex paint mode.
mesh.colors
is unloaded in UnloadMesh
, commenting out that line leads to even more memory being leaked.
I tried to search for instances where a meshes color array pointer was changed in the course of the functions called in the code example, but couldn't find any.
Environment
OS: Arch Linux
Kernel: 6.14.3-arch1-1
CPU: Intel i5-9600K (6) @ 4.700GHz
GPU: NVIDIA GeForce RTX 2070
OpenGL device information:
> Vendor: NVIDIA Corporation
> Renderer: NVIDIA GeForce RTX 2070/PCIe/SSE2
> Version: 3.3.0 NVIDIA 570.144
> GLSL: 3.30 NVIDIA via Cg compiler
Code Example
#include "raylib.h"
int main(int argc, char **argv) {
InitWindow(800, 450, "Test");
Model model;
for (int i = 0; i < 20; i++) {
model = LoadModel("model_with_vertex_colors.glb");
UnloadModel(model);
}
CloseWindow();
return 0;
}
Full log
INFO: Initializing raylib 5.6-dev
INFO: Platform backend: DESKTOP (GLFW)
INFO: Supported raylib modules:
INFO: > rcore:..... loaded (mandatory)
INFO: > rlgl:...... loaded (mandatory)
INFO: > rshapes:... loaded (optional)
INFO: > rtextures:. loaded (optional)
INFO: > rtext:..... loaded (optional)
INFO: > rmodels:... loaded (optional)
INFO: > raudio:.... loaded (optional)
INFO: DISPLAY: Device initialized successfully
INFO: > Display size: 1920 x 1080
INFO: > Screen size: 800 x 450
INFO: > Render size: 800 x 450
INFO: > Viewport offsets: 0, 0
INFO: GLAD: OpenGL extensions loaded successfully
INFO: GL: Supported extensions count: 399
INFO: GL: OpenGL device information:
INFO: > Vendor: NVIDIA Corporation
INFO: > Renderer: NVIDIA GeForce RTX 2070/PCIe/SSE2
INFO: > Version: 3.3.0 NVIDIA 570.144
INFO: > GLSL: 3.30 NVIDIA via Cg compiler
INFO: GL: VAO extension detected, VAO functions loaded successfully
INFO: GL: NPOT textures extension detected, full NPOT textures supported
INFO: GL: DXT compressed textures supported
INFO: GL: ETC2/EAC compressed textures supported
INFO: PLATFORM: DESKTOP (GLFW - X11): Initialized successfully
INFO: TEXTURE: [ID 1] Texture loaded successfully (1x1 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 1] Default texture loaded successfully
INFO: SHADER: [ID 1] Vertex shader compiled successfully
INFO: SHADER: [ID 2] Fragment shader compiled successfully
INFO: SHADER: [ID 3] Program shader loaded successfully
INFO: SHADER: [ID 3] Default shader loaded successfully
INFO: RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)
INFO: RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)
INFO: RLGL: Default OpenGL state initialized successfully
INFO: TEXTURE: [ID 2] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps)
INFO: FONT: Default font loaded successfully (224 glyphs)
INFO: SYSTEM: Working Directory: /home/tatu/_repos/debug-leak
INFO: FILEIO: [../ebb/assets/t.glb] File loaded successfully
INFO: MODEL: [../ebb/assets/t.glb] Model basic data (glb) loaded successfully
INFO: > Meshes count: 1
INFO: > Materials count: 1 (+1 default)
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 2] Unloaded vertex array data from VRAM (GPU)
INFO: MODEL: Unloaded model (and meshes) from RAM and VRAM
INFO: FILEIO: [../ebb/assets/t.glb] File loaded successfully
INFO: MODEL: [../ebb/assets/t.glb] Model basic data (glb) loaded successfully
INFO: > Meshes count: 1
INFO: > Materials count: 1 (+1 default)
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 2] Unloaded vertex array data from VRAM (GPU)
INFO: MODEL: Unloaded model (and meshes) from RAM and VRAM
INFO: FILEIO: [../ebb/assets/t.glb] File loaded successfully
INFO: MODEL: [../ebb/assets/t.glb] Model basic data (glb) loaded successfully
...
INFO: > Meshes count: 1
INFO: > Materials count: 1 (+1 default)
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 2] Unloaded vertex array data from VRAM (GPU)
INFO: MODEL: Unloaded model (and meshes) from RAM and VRAM
INFO: FILEIO: [../ebb/assets/t.glb] File loaded successfully
INFO: MODEL: [../ebb/assets/t.glb] Model basic data (glb) loaded successfully
INFO: > Meshes count: 1
INFO: > Materials count: 1 (+1 default)
INFO: VAO: [ID 2] Mesh uploaded successfully to VRAM (GPU)
INFO: VAO: [ID 2] Unloaded vertex array data from VRAM (GPU)
INFO: MODEL: Unloaded model (and meshes) from RAM and VRAM
INFO: TEXTURE: [ID 2] Unloaded texture data from VRAM (GPU)
INFO: SHADER: [ID 3] Default shader unloaded successfully
INFO: TEXTURE: [ID 1] Default texture unloaded successfully
INFO: Window closed successfully
=================================================================
==276781==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 19200 byte(s) in 200 object(s) allocated from:
#0 0x73b33fafd721 in malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x63a47c3fb49b in LoadGLTF /home/tatu/_repos/raylib/src/rmodels.c:5737
#2 0x63a47c3deba5 in LoadModel /home/tatu/_repos/raylib/src/rmodels.c:1108
#3 0x63a47c287a74 in main (/home/tatu/_repos/debug-leak/build/asan+0x8a74) (BuildId: 04f1efc98355ad39f2ffdaff50800c0ecfebb420)
#4 0x73b33f835487 (/usr/lib/libc.so.6+0x27487) (BuildId: d056ce83eebe65ce7e52ecfa5af5363e4863d283)
#5 0x73b33f83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: d056ce83eebe65ce7e52ecfa5af5363e4863d283)
#6 0x63a47c2878b4 in _start (/home/tatu/_repos/debug-leak/build/asan+0x88b4) (BuildId: 04f1efc98355ad39f2ffdaff50800c0ecfebb420)
Direct leak of 19200 byte(s) in 200 object(s) allocated from:
#0 0x73b33fafd721 in malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x63a47c3fb5f5 in LoadGLTF /home/tatu/_repos/raylib/src/rmodels.c:5745
#2 0x63a47c3deba5 in LoadModel /home/tatu/_repos/raylib/src/rmodels.c:1108
#3 0x63a47c287a74 in main (/home/tatu/_repos/debug-leak/build/asan+0x8a74) (BuildId: 04f1efc98355ad39f2ffdaff50800c0ecfebb420)
#4 0x73b33f835487 (/usr/lib/libc.so.6+0x27487) (BuildId: d056ce83eebe65ce7e52ecfa5af5363e4863d283)
#5 0x73b33f83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: d056ce83eebe65ce7e52ecfa5af5363e4863d283)
#6 0x63a47c2878b4 in _start (/home/tatu/_repos/debug-leak/build/asan+0x88b4) (BuildId: 04f1efc98355ad39f2ffdaff50800c0ecfebb420)
Direct leak of 184 byte(s) in 1 object(s) allocated from:
#0 0x73b33fafd02a in calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x73b33ed48ac3 (/usr/lib/../lib/libdbus-1.so.3+0x24ac3) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#2 0x73b33ed4abbd in _dbus_message_loader_queue_messages (/usr/lib/../lib/libdbus-1.so.3+0x26bbd) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#3 0x73b33ed558ae (/usr/lib/../lib/libdbus-1.so.3+0x318ae) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#4 0x73b33ed55aa7 (/usr/lib/../lib/libdbus-1.so.3+0x31aa7) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#5 0x73b33ed55e00 (/usr/lib/../lib/libdbus-1.so.3+0x31e00) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#6 0x73b33ed5638c (/usr/lib/../lib/libdbus-1.so.3+0x3238c) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#7 0x73b33ed39e92 (/usr/lib/../lib/libdbus-1.so.3+0x15e92) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#8 0x73b33ed4eb9f in dbus_pending_call_block (/usr/lib/../lib/libdbus-1.so.3+0x2ab9f) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#9 0x73b33ed3bd46 in dbus_connection_send_with_reply_and_block (/usr/lib/../lib/libdbus-1.so.3+0x17d46) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#10 0x73b33ed3bfed in dbus_bus_register (/usr/lib/../lib/libdbus-1.so.3+0x17fed) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#11 0x73b33ed3c2da (/usr/lib/../lib/libdbus-1.so.3+0x182da) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#12 0x73b33a430326 (/usr/lib/libstdc++.so.6.0.33+0xc30326)
Indirect leak of 834 byte(s) in 1 object(s) allocated from:
#0 0x73b33fafc3c2 in realloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x73b33ed57566 (/usr/lib/../lib/libdbus-1.so.3+0x33566) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#2 0x73b33ed575f4 (/usr/lib/../lib/libdbus-1.so.3+0x335f4) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#3 0x73b33ed591db in _dbus_string_copy_len (/usr/lib/../lib/libdbus-1.so.3+0x351db) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#4 0x73b33ed4b3ff in _dbus_message_loader_queue_messages (/usr/lib/../lib/libdbus-1.so.3+0x273ff) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#5 0x73b33ed558ae (/usr/lib/../lib/libdbus-1.so.3+0x318ae) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#6 0x73b33ed55aa7 (/usr/lib/../lib/libdbus-1.so.3+0x31aa7) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#7 0x73b33ed55e00 (/usr/lib/../lib/libdbus-1.so.3+0x31e00) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#8 0x73b33ed5638c (/usr/lib/../lib/libdbus-1.so.3+0x3238c) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#9 0x73b33ed39e92 (/usr/lib/../lib/libdbus-1.so.3+0x15e92) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#10 0x73b33ed4eb9f in dbus_pending_call_block (/usr/lib/../lib/libdbus-1.so.3+0x2ab9f) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#11 0x73b33ed3bd46 in dbus_connection_send_with_reply_and_block (/usr/lib/../lib/libdbus-1.so.3+0x17d46) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#12 0x73b33a4929b3 (/usr/lib/libstdc++.so.6.0.33+0xc929b3)
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
#0 0x73b33fafc3c2 in realloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x73b33ed57566 (/usr/lib/../lib/libdbus-1.so.3+0x33566) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#2 0x73b33ed575f4 (/usr/lib/../lib/libdbus-1.so.3+0x335f4) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#3 0x73b33ed591db in _dbus_string_copy_len (/usr/lib/../lib/libdbus-1.so.3+0x351db) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#4 0x73b33ed4abfd in _dbus_message_loader_queue_messages (/usr/lib/../lib/libdbus-1.so.3+0x26bfd) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#5 0x73b33ed558ae (/usr/lib/../lib/libdbus-1.so.3+0x318ae) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#6 0x73b33ed55aa7 (/usr/lib/../lib/libdbus-1.so.3+0x31aa7) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#7 0x73b33ed55e00 (/usr/lib/../lib/libdbus-1.so.3+0x31e00) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#8 0x73b33ed5638c (/usr/lib/../lib/libdbus-1.so.3+0x3238c) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#9 0x73b33ed39e92 (/usr/lib/../lib/libdbus-1.so.3+0x15e92) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#10 0x73b33ed4eb9f in dbus_pending_call_block (/usr/lib/../lib/libdbus-1.so.3+0x2ab9f) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#11 0x73b33ed3bd46 in dbus_connection_send_with_reply_and_block (/usr/lib/../lib/libdbus-1.so.3+0x17d46) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#12 0x73b33ed3bfed in dbus_bus_register (/usr/lib/../lib/libdbus-1.so.3+0x17fed) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#13 0x73b33ed3c2da (/usr/lib/../lib/libdbus-1.so.3+0x182da) (BuildId: 65f44f39f68b8f63de82c45fc6108bfc66c0247a)
#14 0x73b33a430326 (/usr/lib/libstdc++.so.6.0.33+0xc30326)
SUMMARY: AddressSanitizer: 39506 byte(s) leaked in 403 allocation(s).