Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does valgrind say basic SDL program is leaking memory?

Tags:

c++

valgrind

sdl

Here is the SDL program:

#include <SDL/SDL.h>

int main(int argc, char** argv){


  SDL_Init(SDL_INIT_VIDEO);
  SDL_Surface* screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE);
  SDL_Quit();
  return 0;

}

Compiled with the command:

g++ -o test test.cpp -lSDL

And here is the output of valgrind:

christian@christian-laptop:~/cpp/tetris$ valgrind --leak-check=full ./test
==3271== Memcheck, a memory error detector
==3271== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3271== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==3271== Command: ./test
==3271== 
==3271== 
==3271== HEAP SUMMARY:
==3271==     in use at exit: 91,097 bytes in 1,258 blocks
==3271==   total heap usage: 14,250 allocs, 12,992 frees, 2,615,177 bytes allocated
==3271== 
==3271== 10 bytes in 2 blocks are definitely lost in loss record 8 of 134
==3271==    at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==3271==    by 0x4946F04: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4945DA1: _XimEncodeLocalICAttr (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4947195: _XimSetICValueData (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x493FDF1: _XimLocalCreateIC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4922478: XCreateIC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x407AA64: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x407BCBB: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x4069C2A: SDL_VideoInit (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x403F9D3: SDL_InitSubSystem (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x403FA36: SDL_Init (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x8048658: main (in /home/christian/cpp/tetris/test)
==3271== 
==3271== 12 bytes in 1 blocks are definitely lost in loss record 12 of 134
==3271==    at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==3271==    by 0x4A3DA8D: ???
==3271==    by 0x4A3D48C: ???
==3271==    by 0x4A3D5A4: ???
==3271==    by 0x4A3DD26: ???
==3271==    by 0x4A38BC5: ???
==3271==    by 0x4A38FCD: ???
==3271==    by 0x40717DD: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x407BDCA: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x4069C2A: SDL_VideoInit (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x403F9D3: SDL_InitSubSystem (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x403FA36: SDL_Init (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271== 
==3271== 112 (8 direct, 104 indirect) bytes in 1 blocks are definitely lost in loss record 102 of 134
==3271==    at 0x4024D12: realloc (vg_replace_malloc.c:476)
==3271==    by 0x492847E: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492976D: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492AA41: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492B1A4: _XlcCreateLC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x494B4FA: _XlcDefaultLoader (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4933153: _XOpenLC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x49332C2: _XlcCurrentLC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4933761: XSetLocaleModifiers (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x407161D: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x407AD8F: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271==    by 0x407BCBB: ??? (in /usr/lib/libSDL-1.2.so.0.11.2)
==3271== 
==3271== 112 (8 direct, 104 indirect) bytes in 1 blocks are definitely lost in loss record 103 of 134
==3271==    at 0x4024D12: realloc (vg_replace_malloc.c:476)
==3271==    by 0x492847E: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492976D: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492AA41: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x492B1A4: _XlcCreateLC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x494B4FA: _XlcDefaultLoader (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4933153: _XOpenLC (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x493327D: _XrmInitParseInfo (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x4918F20: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x491AF37: XrmGetStringDatabase (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x48F8459: ??? (in /usr/lib/libX11.so.6.2.0)
==3271==    by 0x48F864E: XGetDefault (in /usr/lib/libX11.so.6.2.0)
==3271== 
==3271== LEAK SUMMARY:
==3271==    definitely lost: 38 bytes in 5 blocks
==3271==    indirectly lost: 208 bytes in 8 blocks
==3271==      possibly lost: 0 bytes in 0 blocks
==3271==    still reachable: 90,851 bytes in 1,245 blocks
==3271==         suppressed: 0 bytes in 0 blocks
==3271== Reachable blocks (those to which a pointer was found) are not shown.
==3271== To see them, rerun with: --leak-check=full --show-reachable=yes
==3271== 
==3271== For counts of detected and suppressed errors, rerun with: -v
==3271== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 93 from 14)

Why is this basic SDL program leaking memory?

like image 700
Christian Avatar asked Jan 04 '10 02:01

Christian


People also ask

What is Valgrind memory leak?

Valgrind Memcheck is a tool that detects memory leaks and memory errors. Some of the most difficult C bugs come from mismanagement of memory: allocating the wrong size, using an uninitialized pointer, accessing memory after it was freed, overrunning a buffer, and so on.

What is the main cause of memory leaks?

A memory leak starts when a program requests a chunk of memory from the operating system for itself and its data. As a program operates, it sometimes needs more memory and makes an additional request.

How do you check for memory leaks in C valgrind?

To get the details you need, add --show-leak-kinds=reachable or --show-leak-kinds=all to the Valgrind command line (together with --leak-check=full ). Now you will also get backtraces showing where still reachable memory blocks were allocated in your program.


3 Answers

Even for basic OpenGL "hello world" program without the full SDL, Valgrind gives me similar warnings deep inside the OpenGL libraries. It's peculiar, but I've assumed

  • The library implementors know what they're doing (probably preallocating some small static buffers they never bother to free),
  • Even if they don't, it's a one-time leak that'll be reclaimed by the OS when the program terminates,

and haven't lost much sleep over it.

like image 182
user168715 Avatar answered Oct 24 '22 04:10

user168715


This is normal for the graphics API library (OpenGL, Vulkan, etc) and windowing API (X11, SDL, etc). This best option is to use valgrind suppression files to ignore these errors.

Here is how to do it with Linux, SDL & OpenGL:

Let's say the program you are debugging is called 'prog.out' (remember to replace prog.out with the actual name of your program),

You can export suppression info like this:

valgrind --leak-check=full --show-reachable=yes --show-leak-kinds=all --error-limit=no --gen-suppressions=all --log-file=supdata.log ./prog.out

You can now extract the suppression info from 'supdata.log' using a script or manually. You can use wildcards ('*', '...') to make suppressions more generic (thereby not having to update the suppression file each time you update your code).

After that, whenever you debug your program you would include the suppression file from now on. For example, I made the suppression file below 'linux_sdl_gl.sup'. It works well for me when developing using SDL and OpenGL on Linux. It ignores all of OpenGL, SDL and X11 built in errors so that I can easily find errors I create. Feel free to use it in your development.

When I debug my code I use the following call to valgrind. This allows me to find any new system bugs that my suppression file may have missed.

valgrind --gen-suppressions=all --suppressions=./linux_sdl_gl.sup --leak-check=full --show-leak-kinds=all ./prog.out

file: linux_sdl_gl.sup

# Copyright (c) <'2019'> <'Alrick Grandison'>

# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.

# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:

# 1. The origin of this software must not be misrepresented; you must not
#    claim that you wrote the original software. If you use this software
#    in a product, an acknowledgment in the product documentation would be
#    appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
#    misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.

{
   opengl_memcpy_addr8
   Memcheck:Addr8
   fun:memcpy@GLIBC*
   obj:/usr/lib/x86_64-linux-gnu/dri/*_dri.so
   ...
}

{
   opengl_memcpy_addr1
   Memcheck:Addr1
   fun:memcpy@GLIBC*
   obj:/usr/lib/x86_64-linux-gnu/dri/*_dri.so
   ...
}

{
   opengl_memset_addr8
   Memcheck:Addr8
   fun:memset
   obj:/usr/lib/x86_64-linux-gnu/dri/*_dri.so
   ...
}

{
   sdl_leak_reachable
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
   fun:SDL_Init_REAL
   ...
}

{
   x11_leak_reachable
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
   obj:/usr/lib/x86_64-linux-gnu/libX11.so.*
   ...
}

{
   sdl_leak_indirect
   Memcheck:Leak
   match-leak-kinds: indirect
   ...
   fun:SDL_Init_REAL
   ...
}

{
  sdl_leak_definite
   Memcheck:Leak
   match-leak-kinds: definite
   ...
   fun:SDL_Init_REAL
   ...
}

# OpenGL Calls DL under the Hood - Taken straight out of Valgrind --gen-suppressions
# Could overlap with non-graphics DL api calls
# But, If you are not using DL directly, then don't worry about this
{
   dl_leak_reachable
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
   fun:dlopen@@GLIBC*
   ...
}

# Same as above but more generic
# Could overlap with non-graphics DL api calls
# But, If you are not using DL directly, then don't worry about this
{
   dl_leak_reachable
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
   fun:_dl_*
   ...
}

{
   x11_leak_indirect
   Memcheck:Leak
   match-leak-kinds: indirect
   ...
   obj:/usr/lib/x86_64-linux-gnu/libX11.so.*
   ...
}

{
   x11_leak_definite
   Memcheck:Leak
   match-leak-kinds: definite
   ...
   obj:/usr/lib/x86_64-linux-gnu/libX11.so.*
   ...
}

{
   x11_leak_possible
   Memcheck:Leak
   match-leak-kinds: possible
   ...
   obj:/usr/lib/x86_64-linux-gnu/libX11.so.*
   ...
}

{
   opengl_leak_reachable
   Memcheck:Leak
   match-leak-kinds: reachable
   ...
   obj:/usr/lib/x86_64-linux-gnu/libGLX.so.*
   ...
}

github: valgrind supression code

like image 9
AndreGraveler Avatar answered Oct 24 '22 06:10

AndreGraveler


Every SDL_Surface you load should be freed before the call of SDL_Quit().

To do this, just use SDL_FreeSurface(surfaceName) to free up the surface that you allocated on memory.

like image 1
Petris Rodrigo Fernandes Avatar answered Oct 24 '22 06:10

Petris Rodrigo Fernandes