SDL_Init segfaulting

A very simple code is segfaulting

#include <SDL2/SDL.h>
#include <stdio.h>

void close();

SDL_Window * Window = NULL;

int main(int argc, char *argv[])
{ 
    int retval = 0;
    retval = SDL_Init(SDL_INIT_VIDEO);
    if (retval < 0)
    {
        printf("INIT\n");
        return 1;
    } else {
        //close();
        SDL_DestroyWindow(Window);
        Window = NULL;
        SDL_Quit();
    }
    return 0;
}

void close()
{
    SDL_DestroyWindow(Window);
    Window = NULL;
    SDL_Quit();
}

The funny thing is, if I remove the void close() function and the prototype, even not calling it. The program runs without segfault.

The valgdrind log is a bit long weirdbehavior.txt (65.1 KB)

The ldd output is

linux-vdso.so.1 (0x00007ffc6bb74000)
libSDL2-2.0.so.0 => /lib/x86_64-linux-gnu/libSDL2-2.0.so.0 (0x00007f35dff69000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f35dfda6000)
libasound.so.2 => /lib/x86_64-linux-gnu/libasound.so.2 (0x00007f35dfcad000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f35dfb68000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f35dfb63000)
libpulse.so.0 => /lib/x86_64-linux-gnu/libpulse.so.0 (0x00007f35dfb0f000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f35df9cb000)
libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f35df7b9000)
libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f35df7ac000)
libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f35df7a7000)
libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f35df795000)
libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f35df58a000)
libXss.so.1 => /lib/x86_64-linux-gnu/libXss.so.1 (0x00007f35df583000)
libXxf86vm.so.1 => /lib/x86_64-linux-gnu/libXxf86vm.so.1 (0x00007f35df37d000)
libwayland-egl.so.1 => /lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007f35df378000)
libwayland-client.so.0 => /lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f35df367000)
libwayland-cursor.so.0 => /lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007f35df35e000)
libxkbcommon.so.0 => /lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007f35df31b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f35df2f8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f35e00fd000)
libpulsecommon-13.0.so => /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-13.0.so (0x00007f35df274000)
libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f35df221000)
libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f35df1f7000)
libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f35defed000)
libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f35defe3000)
libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f35defd7000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f35def29000)
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007f35def1d000)
libsndfile.so.1 => /lib/x86_64-linux-gnu/libsndfile.so.1 (0x00007f35deea2000)
libasyncns.so.0 => /lib/x86_64-linux-gnu/libasyncns.so.0 (0x00007f35dee98000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f35dee8d000)
libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f35dec89000)
libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f35dea83000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f35dea5a000)
liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f35dea36000)
libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f35de919000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007f35de8ff000)
libFLAC.so.8 => /lib/x86_64-linux-gnu/libFLAC.so.8 (0x00007f35de8c0000)
libogg.so.0 => /lib/x86_64-linux-gnu/libogg.so.0 (0x00007f35de6b7000)
libvorbis.so.0 => /lib/x86_64-linux-gnu/libvorbis.so.0 (0x00007f35de689000)
libvorbisenc.so.2 => /lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007f35de5dc000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f35de5c4000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f35de5aa000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f35de584000)

Using SDL2 version from system

$ dpkg -l | grep sdl | awk '{printf ("    %35s\t%20s\n",$2,$3)}'
              libsdl-image1.2:amd64	           1.2.12-12
              libsdl-ttf2.0-0:amd64	            2.0.11-6
              libsdl1.2debian:amd64	      1.2.15+dfsg2-5
                libsdl2-2.0-0:amd64	      2.0.12+dfsg1-1
                 libsdl2-2.0-0:i386	      2.0.12+dfsg1-1
         libsdl2-2.0-0-dbgsym:amd64	      2.0.12+dfsg1-1
                  libsdl2-dev:amd64	      2.0.12+dfsg1-1
            libsdl2-gfx-1.0-0:amd64	     1.0.4+dfsg-3+b1
     libsdl2-gfx-1.0-0-dbgsym:amd64	     1.0.4+dfsg-3+b1
              libsdl2-gfx-dev:amd64	     1.0.4+dfsg-3+b1
                    libsdl2-gfx-doc	        1.0.4+dfsg-3
          libsdl2-image-2.0-0:amd64	       2.0.5+dfsg1-2
   libsdl2-image-2.0-0-dbgsym:amd64	       2.0.5+dfsg1-2
            libsdl2-image-dev:amd64	       2.0.5+dfsg1-2
          libsdl2-mixer-2.0-0:amd64	    2.0.4+dfsg1-2+b1
   libsdl2-mixer-2.0-0-dbgsym:amd64	    2.0.4+dfsg1-2+b1
            libsdl2-mixer-dev:amd64	    2.0.4+dfsg1-2+b1
            libsdl2-net-2.0-0:amd64	    2.0.1+dfsg1-4+b1
     libsdl2-net-2.0-0-dbgsym:amd64	    2.0.1+dfsg1-4+b1
              libsdl2-net-dev:amd64	    2.0.1+dfsg1-4+b1
            libsdl2-ttf-2.0-0:amd64	      2.0.15+dfsg1-1
     libsdl2-ttf-2.0-0-dbgsym:amd64	      2.0.15+dfsg1-1
              libsdl2-ttf-dev:amd64	      2.0.15+dfsg1-1

Is this a bug?

Yes, this is a bug - in your code :stuck_out_tongue:

The problem is that close() is a standard C function that is (at least indirectly) used by SDL itself.
You’re basically overriding it with your own close() function, so when SDL tries to call C close() weird things happen (shutdown() is another candidate for bugs like this).
Making it static should fix the issue, or if you need to access it from other .c files rename it (it’s a good idea to use some project-wide prefix for all non-static functions and also types)

Or use C++ and just put everything in your own namespace (though C++ name mangling makes such collisions a lot less likely even without namespaces)

1 Like

Hell… Thanks. So stupid error.

Ohh. no… pls. I can pick other names.

Do you know if GCC has any compilation flag that I can enable to warn about these mistakes?

Hell… Thanks. So stupid error.

You’re certainly not the first to run into this, I know I have :slight_smile:

Do you know if GCC has any compilation flag that I can enable to warn about these mistakes?

I’m not aware of any, but I haven’t searched for one too much - maybe the linker could catch this?
(It couldn’t be perfect, future versions of system libs could introduce new symbols your code can collide with that can’t be detected when you build it, but it’d be better than nothing)
If you find something please share :wink:

1 Like

I’ve been caught by this too; the failure mode can be frustratingly obscure, and code can even run (apparently) correctly if your ‘replacement’ function does something sufficiently similar to the system one! I don’t know of a linker option (other than C+±specific ones) to detect it, but I’d sure like there to be.

1 Like