SDL leaks memory, as reported by valgrind

Even the simplest SDL program leaks memory, as reported by valgrind.

This is the program:

#include "SDL.h"
int main(int argc, char* args[])
{
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Quit();
    return 0;
}

This is the output of valgrind:

==1161== Memcheck, a memory error detector
==1161== Copyright (C) 2002-2015, and GNU GPL’d, by Julian Seward et al.
==1161== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==1161== Command: ./(…omitted…)
==1161==
–1161-- WARNING: Serious error when reading debug info
–1161-- When reading debug info from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0:
–1161-- Ignoring non-Dwarf2/3/4 block in .debug_info
–1161-- WARNING: Serious error when reading debug info
–1161-- When reading debug info from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0:
–1161-- Last block truncated in .debug_info; ignoring
–1161-- WARNING: Serious error when reading debug info
–1161-- When reading debug info from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0:
–1161-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
==1161== Syscall param writev(vector[…]) points to uninitialised byte(s)
==1161== at 0x579EFE0: __writev_nocancel (syscall-template.S:84)
==1161== by 0x8C86F28: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==1161== by 0x8C8731C: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==1161== by 0x8C873A4: xcb_writev (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==1161== by 0x5F3C54D: _XSend (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==1161== by 0x5F3CA41: _XReply (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==1161== by 0x5F2760E: XInternAtom (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==1161== by 0x544EAEA: SetWindowBordered (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x544F8F1: X11_CreateWindow (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x5441148: SDL_CreateWindow_REAL (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x5440F34: SDL_VideoInit_REAL (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x53A8396: SDL_InitSubSystem_REAL (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== Address 0xc18ddb3 is 35 bytes inside a block of size 16,384 alloc’d
==1161== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1161== by 0x5F2C722: XOpenDisplay (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==1161== by 0x5074E69: ??? (in /usr/NX/scripts/vgl/librrfaker.so)
==1161== by 0x50768D1: XOpenDisplay (in /usr/NX/scripts/vgl/librrfaker.so)
==1161== by 0x544DDB4: X11_CreateDevice (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x5440EE0: SDL_VideoInit_REAL (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x53A8396: SDL_InitSubSystem_REAL (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0)
==1161== by 0x40060D: main (in (…omitted…))
==1161==
==1161==
==1161== HEAP SUMMARY:
==1161== in use at exit: 112,141 bytes in 474 blocks
==1161== total heap usage: 10,970 allocs, 10,496 frees, 672,833,828 bytes allocated
==1161==
==1161== LEAK SUMMARY:
==1161== definitely lost: 17,920 bytes in 3 blocks
==1161== indirectly lost: 0 bytes in 0 blocks
==1161== possibly lost: 0 bytes in 0 blocks
==1161== still reachable: 94,221 bytes in 471 blocks
==1161== suppressed: 0 bytes in 0 blocks
==1161== Rerun with --leak-check=full to see details of leaked memory
==1161==
==1161== For counts of detected and suppressed errors, rerun with: -v
==1161== Use --track-origins=yes to see where uninitialised values come from
==1161== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 1 from 1)

So my question is: Does SDL have to leak memory? Is there any workaround to stop the leakage? Thanks.

Environment:

  • Ubuntu 16.04 64 bit.
  • SDL 2.0
  • g++ 5.4.0
  • Valgrind 3.11.0

A follow-up: this is the valgrind report of leakage on another Linux:


Environment:

  • Ubuntu 18.04 64 bit.
  • SDL 2.0
  • g++ 7.3.0
  • Valgrind 3.13.0

This is a known issue with X11 and some other libraries on Linux. They do not actually leak but are detected as leaks.

1 Like

Hi, still open.
using mint21.2 with cinnamon i get a leak message with “widelands”

>     [03:52:10.490 real] INFO: SoundHandler: Closing 1 time, 22050 Hz,
>     format
>     32784, 2 channels
>     [03:52:10.490 real] INFO: SoundHandler: SDL_AUDIODRIVER pulseaudio
>
>     =================================================================
>     ==11630==ERROR: LeakSanitizer: detected memory leaks
>
>     Direct leak of 160 byte(s) in 1 object(s) allocated from:
>           #0 0x7f0e78e35a57 in __interceptor_calloc
>     ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
>           #1 0x7f0e76d4dd3f
>     (/lib/x86_64-linux-gnu/libSDL2-2.0.so.0+0xf7d3f)
>
>     SUMMARY: AddressSanitizer: 160 byte(s) leaked in 1 allocation(s).
>
> 

After email
On 8/7/24 21:22, Sam Lantinga wrote:

Can you build SDL with debug symbols and get a stack trace of where this
allocation occurred?

i now would like to build it
but this thread says PERHAPS its a faulty message ???
and
what will i need to build the debug symbols
OR/AND how to check if its already done?
cheers

i am native z80;-)

Sorry, to not answer your questions about building SDL with debug flags, but I want to draw your attention to this and I hope it works for your project:

There was a recent issue that Chvolow24 reported and solved here on a Mac system where the Address Sanitizer was actually the culprit in causing a leak linked to it’s trying to track memory being passed between the audio driver and SDL audio device.
I see you are on Linux, but your output mentions the Address Sanitizer and Audio Drivers. Perhaps the Sanitizer is still a problem here.

What happens if you remove Address Sanitizer from your compiler arguments and use Valgrind instead?

Edit:
To (hopefully) answer your actual question, you can build a debug version using this cmake argument:
cmake ~/SDL -DCMAKE_BUILD_TYPE=Debug

HI, thanks for your reply, the sanitiser report is made by widelands widelands.org
its a big auto install once the dev are complete and i have no clue if Address Sanitizer and Valgrind are equal in use
for an SDL install i probably have to download it first and check a lot off dev, i use synaptic for regular installs but i do install eg z88dk

edit:
found on widelands org the install line
$ ./compile.sh -r for a release build, or $ ./compile.sh -a for a debug build without AddressSanitizer
i better do that first.

Hello,

Sorry to play necromancer with this subject but I have a similar problem with the SDL3 on debian 13 so interracting with Wayland not X11.

With the following code :

File Edit Options Buffers Tools C Help                                                                                                                                                                             
#include <SDL3/SDL.h>

int             main(void)
{
  SDL_Window    *window;
  SDL_Renderer  *renderer;
  int           ret;

  ret = SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
  if (ret != 0)
    {
      SDL_LogError(SDL_LOG_CATEGORY_ERROR, "[DEBUG] > %s", SDL_GetError());
      return (-1);
    }
  window = SDL_CreateWindow("MyGameOfLife", 800, 600, SDL_WINDOW_MOUSE_FOCUS);
  if (window == NULL)
    {
      SDL_LogError(SDL_LOG_CATEGORY_ERROR, "[DEBUG] > %s", SDL_GetError());
      return (-1);
    }
  renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED);
  if (renderer == NULL)
    {
      SDL_LogError(SDL_LOG_CATEGORY_ERROR, "[DEBUG] > %s", SDL_GetError());
      return (-1);
    }

  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);

  return (0);
}

==15917== 1 errors in context 1 of 79:
==15917== Invalid read of size 8
==15917==    at 0x4023B94: strncmp (strcmp-sse2.S:162)
==15917==    by 0x4004B9E: is_dst (dl-load.c:216)
==15917==    by 0x4005A0D: _dl_dst_substitute (dl-load.c:295)
==15917==    by 0x4005CB2: fillin_rpath.isra.0 (dl-load.c:483)
==15917==    by 0x4005FA2: decompose_rpath (dl-load.c:654)
==15917==    by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917==    by 0x4002260: openaux (dl-deps.c:64)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917==    by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917==  Address 0x6a76749 is 9 bytes inside a block of size 15 alloc'd
==15917==    at 0x48417B4: malloc (vg_replace_malloc.c:381)
==15917==    by 0x402397A: malloc (rtld-malloc.h:56)
==15917==    by 0x402397A: strdup (strdup.c:42)
==15917==    by 0x4005F34: decompose_rpath (dl-load.c:629)
==15917==    by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917==    by 0x4002260: openaux (dl-deps.c:64)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917==    by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x400B5B7: _dl_open (dl-open.c:884)
==15917== 
==15917== 
==15917== 1 errors in context 2 of 79:
==15917== Invalid read of size 8
==15917==    at 0x4023B94: strncmp (strcmp-sse2.S:162)
==15917==    by 0x4004B9E: is_dst (dl-load.c:216)
==15917==    by 0x400596E: _dl_dst_count (dl-load.c:253)
==15917==    by 0x4005B47: expand_dynamic_string_token (dl-load.c:395)
==15917==    by 0x4005CB2: fillin_rpath.isra.0 (dl-load.c:483)
==15917==    by 0x4005FA2: decompose_rpath (dl-load.c:654)
==15917==    by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917==    by 0x4002260: openaux (dl-deps.c:64)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917==    by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==  Address 0x6a76749 is 9 bytes inside a block of size 15 alloc'd
==15917==    at 0x48417B4: malloc (vg_replace_malloc.c:381)
==15917==    by 0x402397A: malloc (rtld-malloc.h:56)
==15917==    by 0x402397A: strdup (strdup.c:42)
==15917==    by 0x4005F34: decompose_rpath (dl-load.c:629)
==15917==    by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917==    by 0x4002260: openaux (dl-deps.c:64)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917==    by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917==    by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917==    by 0x400B5B7: _dl_open (dl-open.c:884)
==15917== 
==15917== ERROR SUMMARY: 79 errors from 79 contexts (suppressed: 0 from 0)

run with :

valgrind -s --leak-check=full --show-leak-kinds=all ./a.out

I get errors like this:

==15917== 107,648 bytes in 464 blocks are still reachable in loss record 2,687 of 2,688
==15917== at 0x48417B4: malloc (vg_replace_malloc.c:381)
==15917== by 0x625C192: ??? (in /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0)
==15917== by 0x627255E: ??? (in /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0)
==15917== by 0x6263DE8: ??? (in /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0)
==15917== by 0x625F6F3: ??? (in /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0)
==15917== by 0x4A343AC: X11_GL_GetVisual (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x4A3332E: X11_GL_InitExtensions (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x4A33032: X11_GL_LoadLibrary (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x49A5CBE: SDL_GL_LoadLibrary_REAL (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x49A1AAC: SDL_RecreateWindow (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x48DC0B3: GL_CreateRenderer (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x48CB849: SDL_CreateRendererWithProperties_REAL (in /usr/local/lib/libSDL3.so.0.0.0)
==15917==
==15917== 472,368 bytes in 1 blocks are still reachable in loss record 2,688 of 2,688
==15917== at 0x484682F: realloc (vg_replace_malloc.c:1437)
==15917== by 0x5A3C057: ??? (in /usr/lib/x86_64-linux-gnu/libX11.so.6.4.0)
==15917== by 0x5A39F4C: _XimLocalOpenIM (in /usr/lib/x86_64-linux-gnu/libX11.so.6.4.0)
==15917== by 0x5A38687: _XimOpenIM (in /usr/lib/x86_64-linux-gnu/libX11.so.6.4.0)
==15917== by 0x4A2E298: X11_InitKeyboard (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x4A36B22: X11_VideoInit (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x499E2DA: SDL_VideoInit (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x48731D7: SDL_InitSubSystem_REAL (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x48733E0: SDL_Init_REAL (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x4892025: SDL_Init_DEFAULT (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x489B922: SDL_Init (in /usr/local/lib/libSDL3.so.0.0.0)
==15917== by 0x1091AA: main (in /home/n0b0dy/Dev/sandbox/a.out)
==15917==

==15917== LEAK SUMMARY:
==15917== definitely lost: 0 bytes in 0 blocks
==15917== indirectly lost: 0 bytes in 0 blocks
==15917== possibly lost: 70,737 bytes in 169 blocks
==15917== still reachable: 1,387,873 bytes in 5,269 blocks
==15917== suppressed: 0 bytes in 0 blocks
==15917==
==15917== ERROR SUMMARY: 79 errors from 79 contexts (suppressed: 0 from 0)
==15917==
==15917== 1 errors in context 1 of 79:
==15917== Invalid read of size 8
==15917== at 0x4023B94: strncmp (strcmp-sse2.S:162)
==15917== by 0x4004B9E: is_dst (dl-load.c:216)
==15917== by 0x4005A0D: _dl_dst_substitute (dl-load.c:295)
==15917== by 0x4005CB2: fillin_rpath.isra.0 (dl-load.c:483)
==15917== by 0x4005FA2: decompose_rpath (dl-load.c:654)
==15917== by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917== by 0x4002260: openaux (dl-deps.c:64)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917== by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917== Address 0x6a76749 is 9 bytes inside a block of size 15 alloc’d
==15917== at 0x48417B4: malloc (vg_replace_malloc.c:381)
==15917== by 0x402397A: malloc (rtld-malloc.h:56)
==15917== by 0x402397A: strdup (strdup.c:42)
==15917== by 0x4005F34: decompose_rpath (dl-load.c:629)
==15917== by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917== by 0x4002260: openaux (dl-deps.c:64)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917== by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x400B5B7: _dl_open (dl-open.c:884)
==15917==
==15917==
==15917== 1 errors in context 2 of 79:
==15917== Invalid read of size 8
==15917== at 0x4023B94: strncmp (strcmp-sse2.S:162)
==15917== by 0x4004B9E: is_dst (dl-load.c:216)
==15917== by 0x400596E: _dl_dst_count (dl-load.c:253)
==15917== by 0x4005B47: expand_dynamic_string_token (dl-load.c:395)
==15917== by 0x4005CB2: fillin_rpath.isra.0 (dl-load.c:483)
==15917== by 0x4005FA2: decompose_rpath (dl-load.c:654)
==15917== by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917== by 0x4002260: openaux (dl-deps.c:64)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917== by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== Address 0x6a76749 is 9 bytes inside a block of size 15 alloc’d
==15917== at 0x48417B4: malloc (vg_replace_malloc.c:381)
==15917== by 0x402397A: malloc (rtld-malloc.h:56)
==15917== by 0x402397A: strdup (strdup.c:42)
==15917== by 0x4005F34: decompose_rpath (dl-load.c:629)
==15917== by 0x400815B: _dl_map_object (dl-load.c:2111)
==15917== by 0x4002260: openaux (dl-deps.c:64)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x40025C9: _dl_map_object_deps (dl-deps.c:232)
==15917== by 0x400BA6C: dl_open_worker_begin (dl-open.c:592)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x400B1C5: dl_open_worker (dl-open.c:782)
==15917== by 0x4C58219: _dl_catch_exception (dl-error-skeleton.c:208)
==15917== by 0x400B5B7: _dl_open (dl-open.c:884)
==15917==
==15917== ERROR SUMMARY: 79 errors from 79 contexts (suppressed: 0 from 0)

in addition to the “fake errors” what is not nothing if we consider I have done nothing yet but just initialized SDL, created a window and a renderer and cleaned everything.

What causes the fake leaks please?

Am I condamned to use a valgrind errors suppression file to hide the internal errors to be able to debug my program?

@paulo951 Does calling SDL_Quit help with the memory leaks? As for the invalid reads in _dl_open, this page says it’s an issue with Valgrind versions older than 3.20.

(Assuming you have an SDL_Quit() call at the end of the program) These are usually leaks in X11 and OpenGL libraries and not SDL, and (against reason) may even be intentional leaks on their part.

Please report them to those projects.

Also: this used XWayland in this case (since it used SDL’s X11 backend). You can force SDL to talk to Wayland directly with the SDL_VIDEODRIVER=wayland environment variable (in SDL2. In SDL3, it’s SDL_VIDEO_DRIVER, extra underscore).