3
votes

I just finished a tetris clone using SDL 1.2, now I'm trying to make a better version using SDL2. But I'm getting segmentation fault and I don't know why.

Here's the valgrind report:

==9471== Memcheck, a memory error detector
==9471== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==9471== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==9471== Command: ./tetris
==9471== 
==9471== Thread 2:
==9471== Invalid read of size 8
==9471==    at 0xB4B57A9: ??? (in /usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.319.82)
==9471==    by 0x4E8094E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E799EA: SDL_CreateTexture (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E79C6D: SDL_CreateTextureFromSurface (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x401176: load_texture.3137.2439 
==9471==    by 0x401194: video_load_image.2436
==9471==    by 0x4011B6: block_image_load_all.2429
==9471==    by 0x4017BD: run_game_logic.2384
==9471==    by 0x541B061: start_thread (pthread_create.c:312)
==9471==    by 0x5715A3C: clone (clone.S:111)
==9471==  Address 0x8c0 is not stack'd, malloc'd or (recently) free'd
==9471== 
==9471== 
==9471== Process terminating with default action of signal 11 (SIGSEGV)
==9471==  Access not within mapped region at address 0x8C0
==9471==    at 0xB4B57A9: ??? (in /usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.319.82)
==9471==    by 0x4E8094E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E799EA: SDL_CreateTexture (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E79C6D: SDL_CreateTextureFromSurface  (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x401176: load_texture.3137.2439
==9471==    by 0x401194: video_load_image.2436
==9471==    by 0x4011B6: block_image_load_all.2429
==9471==    by 0x4017BD: run_game_logic.2384
==9471==    by 0x541B061: start_thread (pthread_create.c:312)
==9471==    by 0x5715A3C: clone (clone.S:111)
==9471==  If you believe this happened as a result of a stack
==9471==  overflow in your program's main thread (unlikely but
==9471==  possible), you can try to increase the size of the
==9471==  main thread stack using the --main-stacksize= flag.
==9471==  The main thread stack size used in this run was 8388608.

And the functions:

SDL_Texture *video_load_image(const char *file)
{
    return load_texture(file);
}

static SDL_Texture *load_texture(const char *path)
{
    SDL_Surface *surface;
    SDL_Texture *texture;

    if((surface = SDL_LoadBMP(path)) == NULL){
        puts("invalid path");
        return NULL;
    }

    texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);

    return texture;
}

char *image_path[BLOCK_COUNT] = {
    "img/block_dark_cyan32.bmp", "img/block_dark_red32.bmp",
    "img/block_dark_brown32.bmp", "img/block_dark_magenta32.bmp",
    "img/block_dark_gray32.bmp", "img/block_dark_green32.bmp",
    "img/block_dark_blue32.bmp", 
    "img/block_wall32.bmp", "img/block_empty32.bmp"
};

SDL_Texture *textures[BLOCK_COUNT];

int block_image_load_all(void)
{
    for(int i = 0; i < BLOCK_COUNT; ++i){
        if((textures[i] = video_load_image(image_path[i])) == NULL){
            while(i > 0)
                video_free_image(textures[--i]);

            return ERROR;
        }
    }

    return SUCCESS;
}

What is causing segmentation fault here?

Update: switching the renderer to SDL_RENDERER_SOFTWARE solves the problem, but I would like to use SDL_RENDERER_ACCELERATED

I don't think the problem is the driver since I'm using SDL_RENDERER_ACCELERATED successfully in another program.

3
Is renderer fully initialised at the time of textures loading? Are you sure your OpenGL driver operating correctly? Test it with glxinfo and glxgears, at least. Also, valgrind is memory debugger; in case of crashes, it is better to use ordinary debugger like gdb (but it is not directly related to your problem) - keltar
@keltar I believe it's something to do with this code or images because the SDL_RENDERER_ACCELERATED flag works correctly in another similar project. - 2013Asker
@keltar I tested with both as you suggested, no problems there. Is it possible that the image format is the problem? I created the blocks using gimp and exported as ARGB 32 bits. - 2013Asker
You don't show BLOCK_COUNT's definition in your code - if it's more than the number of strings in image_path then you may call video_load_image with a null pointer. - M.M
@2013Asker how about you make complete compilable minimal example including one of your problematic images and upload it somewhere? There could be many reasons, but it is impossible to say by just these code fragments. - keltar

3 Answers

1
votes

Make sure when using the SDL_CreateRender() to put -1 as your second argument so SDL auto chooses a valid Video Card to use.

If problem persists, then update your Video Card drivers (restart computer after) .

Comment if it still persists

0
votes

I don't think the problem is the driver since I'm using SDL_RENDERER_ACCELERATED successfully in another program.

Yes, in all probable there would be problem in your program and not in the library.Looking the Valgrind error report, your program seems to have in big mess and memory is getting corrupted.This is is bit difficult to find by looking out your code snippet. There could be three probable reason of your problem:

  1. Heap Memory Overflow/Reading After freeing the memory.
  2. Stack Overflow Scenario.
  3. Synchronization problem in threads which resulting into some form of memory corruption.

All these problem are pretty difficult to identify and there is not sort cut way to find such bugs in big programs except debugging. You may want to refer my previous post on Valgrind/GDB and Helgrind.

https://stackoverflow.com/a/22658693/2724703

https://stackoverflow.com/a/22617989/2724703

0
votes

It doesn't look like you free the font in your code. Try:

TTF_CloseFont(TTF_Font *font);

after you finish using the font or it will cause a segmentation fault after a few hundred frames.