Forum Programmation.c erreur de segmentation sur SDL_Init

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
21
avr.
2021

bonjour,
j'utilise actuellement la SDL2. Je viens de m'y mettre.
Je sais lier les librairies vu que j'utilisais déjà la version 1.2.
Le problème est qu'après avoir lu les tuto de lazy foo, qui fonctionnent très bien en c++, une fois reformaté et compilé en c j'ai un problème avec la SDL_Init.
Voici ce que me renvoie le débogueur :

(gdb) s
76      if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x3) at malloc.c:2966
2966    malloc.c: Aucun fichier ou dossier de ce type.

Est-ce que quelqu'un aurait une idée de ce qu'il peut se passer?
cordialement

  • # Corruption mémoire

    Posté par  . Évalué à 2.

    Ceci est dû à une corruption de la zone mémoire où est gérée les allocations mémoires (malloc/free).
    Donc quand SDL_Init appelle free il va tomber sur une adresse corrompue => segmentation fault.
    Il y a donc avant l'appel de SDL_Init, probablement un débordement de buffer sur une zone allouée par un malloc.

    • [^] # Re: Corruption mémoire

      Posté par  . Évalué à 4.

      J'ai pas compris pourquoi tu as été moissé, ta réponse est tout à fait pertinente et c'est très probable que ce soit la bonne.
      Une façon simple de vérifier cela est de mettre ton sdl_init en tout premier dans ton main, à priori il devrait passer.
      Ensuite reste à trouver la corruption mémoire, si tu n'y arrives pas en lisant ton code, des outils comme valgrind ou asan peuvent grandement t'aider.

    • [^] # Re: Corruption mémoire

      Posté par  . Évalué à 3.

      Un exemple pour reproduire le problème:

      uint8_t* k = (uint8_t*)malloc(10);
      uint8_t* k2 = (uint8_t*)malloc(15);
      
      memset(k,0,25); // écrasement de la zone mémoire allouée par k2
      
      free(k2);  // segfault 
      
  • # pas de corruption mémoire

    Posté par  . Évalué à 1.

    Et non, j'aurais dû le préciser par ailleurs.
    J'appelle mon SDL_Init en tout début de code.
    J'ai juste déclaré quelques variables avant en les initialisant soit à NULL soit à 0.
    Je ne vois vraiment pas d'où vient le problème!
    Surtout que, comme je le répète, j'ai seulement modifié un code c++ en code c sans toucher à l'organisation des fonctions…
    C'est à n'y rien comprendre.

    • [^] # Re: pas de corruption mémoire

      Posté par  . Évalué à 3.

      Talk is cheap, show us the code

      Ensuite on test, et on trouvera

      Amiralgaby#1847

    • [^] # Re: pas de corruption mémoire

      Posté par  . Évalué à 2.

      tu as l'initialisation des variables statiques/globales avant l'appel de main, ton code peut donc créer des soucis avant main.
      Comme dit plus haut, si tu veux qu'on t'aide à trouver le problème, il nous faut le code (meme une version très simplifiée ou tu vires quasiment tout)
      Sinon, on peut juste te donner des pistes et des moyens pour te débrouiller par toi meme.
      Tu as fais un run valgrind ? tu as quoi comme résultat ?

  • # Ça sent une incompatibilité binaire

    Posté par  (site web personnel) . Évalué à 2.

    Ça me parait très bizarre comme problème. Ton système est à jour ? tu es sous quelle distribution ?

    Tu utilises bien la SDL 2 fournie par ton système ? pas installée à la main ou autre ?

    git is great because linus did it, mercurial is better because he didn't

  • # paquage sdl2 de stretch

    Posté par  . Évalué à 1.

    oui j'utilise la version de ma distribution.
    J'ai utilisé valgrind -v sans plus de résultats.
    Quant à gdb, maintenant il m'indique pour SDL_Init:

    Program received signal SIGSEGV, Segmentation fault.
    0x00007ffff781536c in ?? () from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0
    

    Je n'ai plus la même erreur sans rien avoir touché.
    ET POURTANT, lorsque je vire la quasi totalité de mon code pour nelaisser que ma fonction d'initialisation, SDL_Init se comporte à ravir…
    Je vous refile la totalité de mon code, je n'arrive pas à le formater pour qu'il rende dans les balises:

    #include <SDL2/SDL.h>
    #include <SDL2/SDL_image.h>
    #include <SDL2/SDL_ttf.h>
    #include <stdio.h>
    #include<stdlib.h>
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    SDL_Window* gWindow = NULL;
    SDL_Renderer* gRenderer = NULL;
    TTF_Font *gFont = NULL;
    void free1(SDL_Texture *mTexture)
    {
        //Free texture if it exists
        if( mTexture != NULL )
        {
            SDL_DestroyTexture( mTexture );
            mTexture = NULL;
        }
    }
    int loadFromRenderedText(SDL_Texture *mTexture, char textureText[200], SDL_Color textColor, SDL_Rect *position )
    {
        //Get rid of preexisting texture
        free1(mTexture);
        //Render text surface
        SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText, textColor );
        if( textSurface == NULL )
        {
            printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
        }
        else
        {
            //Create texture from surface pixels
            mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
            if( mTexture == NULL )
            {
                printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
            }
            else
            {
                //Get image dimensions
                position->w = textSurface->w;
                position->h = textSurface->h;
            }
            //Get rid of old surface
            SDL_FreeSurface( textSurface );
        }
        //Return success
        return mTexture != NULL;
    }
    void render(SDL_Texture *mTexture, SDL_Rect* clip)
    {
        SDL_RenderCopy( gRenderer, mTexture, clip, clip);
    }
    int init()
    {
        //Initialization flag
        int success = 1;
        //Initialize SDL
        if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        {
            printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
            success = 0;
        }
        else
        {
            //Set texture filtering to linear
            if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
            {
                printf( "Warning: Linear texture filtering not enabled!" );
            }
            //Create window
            gWindow = SDL_CreateWindow( "SDL Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
            if( gWindow == NULL )
            {
                printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
                success = 0;
            }
            else
            {
                //Create vsynced renderer for window
                gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
                if( gRenderer == NULL )
                {
                    printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
                    success = 0;
                }
                else
                {
                    //Initialize renderer color
                    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                    //Initialize PNG loading
                    int imgFlags = IMG_INIT_PNG;
                    if( !( IMG_Init( imgFlags ) & imgFlags ) )
                    {
                        printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
                        success = 0;
                    }
                     //Initialize SDL_ttf
                    if( TTF_Init() == -1 )
                    {
                        printf( "SDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError() );
                        success = 0;
                    }
                }
            }
        }
        return success;
    }
    int loadMedia(SDL_Texture *mTexture, SDL_Rect *position)
    {
        //Loading success flag
        int success = 1;
        //Open the font
        gFont = TTF_OpenFont( "lazy.ttf", 28 );
        if( gFont == NULL )
        {
            printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
            success = 0;
        }
        else
        {
            //Render text
            SDL_Color textColor = { 0, 0, 0, 255};
            char text[200];
            sprintf(text, "The quick brown fox jumps over the lazy dog");
            if( !loadFromRenderedText(mTexture, text, textColor, position ) )
            {
                printf( "Failed to render text texture!\n" );
                success = 0;
            }
        }
        return success;
    }
    void close(SDL_Texture *mTexture)
    {
        SDL_DestroyTexture( mTexture );
        mTexture = NULL;
        //Free global font
        TTF_CloseFont( gFont );
        gFont = NULL;
        //Destroy window    
        SDL_DestroyRenderer( gRenderer );
        SDL_DestroyWindow( gWindow );
        gWindow = NULL;
        gRenderer = NULL;
        //Quit SDL subsystems
        TTF_Quit();
        IMG_Quit();
        SDL_Quit();
    }
    int main( int argc, char* args[] )
    {
        SDL_Texture* mTexture = NULL;
        SDL_Rect position;
        position.x = 100;
        position.y = 100;
        position.w = 0;
        position.h = 0;
        //Start up SDL and create window
        if( !init() )
        {
            printf( "Failed to initialize!\n" );
        }
        else
        {
            //Load media
            if( !loadMedia(mTexture, &position) )
            {
                printf( "Failed to load media!\n" );
            }
            else
            {   
                //Main loop flag
                int quit = 0;
                //Event handler
                SDL_Event e;
                //While application is running
                while( !quit )
                {
                    //Handle events on queue
                    while( SDL_PollEvent( &e ) != 0 )
                    {
                        //User requests quit
                        if( e.type == SDL_QUIT )
                        {
                            quit = 1;
                        }
                    }
                    //Clear screen
                    //SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
                    //SDL_RenderClear( gRenderer );
                    ////Render current frame
                    //render(mTexture, &position );
                    ////Update screen
                    //SDL_RenderPresent( gRenderer );
                }
            }
        }
        //Free resources and close SDL
        close(mTexture);
        return 0;
    }
    

    meric pour votre retour. à bientôt!

    • [^] # Re: paquage sdl2 de stretch

      Posté par  . Évalué à 2.

      Renomme la fonction close() en Xclose(), par exemple et ça marchera.
      Ca doit clasher avec la fonction close(2), je suppose ? Il faudra demander à plus expert que moi.

      • [^] # Re: paquet sdl2 de stretch

        Posté par  (site web personnel) . Évalué à 2.

        Je vois le même SIGSEGV sur bullseye :

        Program received signal SIGSEGV, Segmentation fault.
        0x00007ffff7e7fffc in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        (gdb) bt
        #0  0x00007ffff7e7fffc in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #1  0x000055555555565e in close ()
        #2  0x00007ffff7038bd4 in _dbus_close () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #3  0x00007ffff7036bef in _dbus_file_get_contents () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #4  0x00007ffff7032fb1 in ?? () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #5  0x00007ffff703a2ff in _dbus_read_local_machine_uuid () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #6  0x00007ffff70331e7 in _dbus_get_local_machine_uuid_encoded () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #7  0x00007ffff70276bf in dbus_try_get_local_machine_id () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #8  0x00007ffff7027774 in dbus_get_local_machine_id () from /lib/x86_64-linux-gnu/libdbus-1.so.3
        #9  0x00007ffff7f228ed in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #10 0x00007ffff7f2301b in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #11 0x00007ffff7f2251f in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #12 0x00007ffff7f073ff in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #13 0x00007ffff7f0e467 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #14 0x00007ffff7ee8db3 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #15 0x00007ffff7e41f47 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
        #16 0x00005555555553e9 in init ()
        #17 0x0000555555555703 in main ()
        

        et une fois que le close() du fichier principal est renommé en autre chose, ça se passe beaucoup mieux. Sans cela, on a :

        kibi@tokyo:/tmp$ gcc -O0 foo.c  -lSDL2 -lSDL2_image -lSDL2_ttf && nm -D a.out | grep close
        0000000000001646 T close
        

        et le symbole close est défini dans l'exécutable. close étant (également) un appel système fréquemment utilisé (plus haut, dans libdbus), boum.

        Debian Consultant @ DEBAMAX

        • [^] # Re: paquet sdl2 de stretch

          Posté par  . Évalué à 1.

          Ah oui ! J'ai essayé sur une stretch comme l'auteur original.
          Un strace me donne shutdown(2) comme dernière fonction appelée. Donc Si cette fonction a besoin d'appeler close() cela appelerait en fait la version redéfinie en fait ?

  • # ça marche

    Posté par  . Évalué à 2.

    ouai!! merci les gars.
    à+

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.