[C/SDL2] SDL_Window* par argument dans une fonction - SegFault

Comprendre une erreur de segmentation

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Voilà le problème: Je souhaite factoriser la création d’une fenêtre en SDL2 à l’aide d’une fonction. Bien entendu cela ne marche pas, GCC me vomi dessus (SegFault). Le problème selon GDB vient de la ligne 20. Je sais pourquoi cela ne marche pas mais je ne sait pas comment résoudre le problème.

Comment faut-il passer un pointeur de type SDL_Window* ou autre dans les arguments d’une fonction et quel en doit être ses paramètres afin que le pointeur de la fonction main soit modifié ? J’ai à peu près tout essayé même un pointeur de pointeur mais cela ne fonctionne pas.

Options de compilation: gcc hellodsl.c -g -Wall -Wextra -pedantic -O2 -ansi -lSDL2 -o hellosdl

Voici le code:

Hellosdl.c (La librairie SDL2 est définie dans son header qui ne fait que prototyper les fonctions)

#include "hellosdl.h"

/* Screen dimension constants */
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main(void)
{
    SDL_Window* mainWindow = NULL;
    SDL_Surface* mainWindowSurface = NULL;

    if(initSDL(SDL_INIT_VIDEO) < 1)
        return EXIT_FAILURE;

    if(createWindow(mainWindow, "Hello SDL", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN) < 1)
        return EXIT_FAILURE;

    /* Fill the surface white */
    
    mainWindowSurface = SDL_GetWindowSurface(mainWindow);
    SDL_FillRect(mainWindowSurface, NULL, SDL_MapRGB(mainWindowSurface->format, 0xFF, 0xFF, 0xFF));
            
    /* Update the surface */
    SDL_UpdateWindowSurface(mainWindow);

    /* Wait two seconds */
    SDL_Delay(2000);

    /* Destroy window */
    
    SDL_DestroyWindow(mainWindow);

    /* Quit SDL subsystems */
    SDL_Quit();

    return EXIT_SUCCESS;
}

void displayError(const char* title, SDL_Window* window)
{
    if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, SDL_GetError(), window) < 0)
        fprintf(stderr, "SDL error occured: %s\n", SDL_GetError());
}

int initSDL(Uint32 flag)
{
    if(SDL_Init(flag) < 0)
    {
        displayError("SDL Initialization Error", NULL);
        return 0;
    }

    return 1;
}

int createWindow(SDL_Window* window, const char* title, int x, int y, int w, int h, Uint32 windowFlag)
{
    window = SDL_CreateWindow(title, x, y, w, h, windowFlag);

    if(window == NULL)
    {
        displayError(title, NULL);
        return 0;
    }

    return 1;
}

Merci d’avance !

Salut,

Ta fonction createWindow doit modifier ton pointeur window, il te faut donc passer par un double pointeur SDL_Window **. Ou sinon, tu peux faire ta fonction retourner un SDL_Window *.

PS : pourquoi passer par des surfaces ? Ici, tu n’en as pas besoin.

+0 -0

Yo,

Merci à toi, justement j’ai tenté d’implémenter ça avec un double pointeur mais n’ayant pas trop eu à faire à ceux ci je me suis emêler les pinceaux.

Retourner un SDL_Window* est une solution à laquelle j’avais pensé mais que je n’ai pas implémenter, je souhaiter éviter d’assigner une valeur de retour à mon pointeur, quoique si en fait je pourrai le faire.

Pour l’histoire des surfaces, je m’adapte de ce cours -> LazyFoo', je ne connais pas encore toute la SDL2

Hum … Par pointeur :

int createWindow(SDL_Window** window, const char* title, int x, int y, int w, int h, Uint32 windowFlag)
{
    if(window == NULL) {
        displayError(title, NULL);
        return 0;
    }

    *window = SDL_CreateWindow(title, x, y, w, h, windowFlag);

    if(*window == NULL)
    {
        displayError(title, NULL);
        return 0;
    }

    return 1;
}

Avec comme appel :

    SDL_Window* mainWindow = NULL;

    // [...] 

    if(createWindow(&mainWindow, "Hello SDL", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN) < 1)
        return EXIT_FAILURE;

Si ce n’est pas ce que tu avais fait alors tu devrais essayer de comprendre pourquoi c’est comme ça. Quite à relire un cours sur le langage C pour t’aider.

Mais le plus logique selon moi serait de retourner un pointeur :

SDL_Window* createWindow(const char* title, int x, int y, int w, int h, Uint32 windowFlag)
{
    SDL_Window* window;
    window = SDL_CreateWindow(title, x, y, w, h, windowFlag);

    if(window == NULL)
    {
        displayError(title, NULL);
        return NULL;
    }

    return window;
}

Utilisez comme ceci :

    SDL_Window* mainWindow = NULL;

    // [...] 
    mainWindow = createWindow("Hello SDL", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN)
    if( mainWindows == NULL )
        return EXIT_FAILURE;

Comme l’avait proposer Karnaj.

+0 -0

Merci à tous les deux.

Cela fait un petit moment que je n’ai plus fait de C j’avoue. Ta solution par pointeur marche parfaitement, je préfère utiliser celle-ci car les erreurs y sont gérées en interne par l’appel de la fonction displayError(). (Factorisation)

C’est pratiquement ce que j’avais fait, sauf que j’avais omis un * devant le paramètre window quant la fonction createWindow() teste si le double pointeur est NULL avant de faire appel à la fonction displayError().

En tant qu’autodidacte je n’aime pas appliquer bêtement quelque chose. Donc pourquoi cela marche comme ça ?

J’ai bien une piste: SDL_Window* n’est pas un simple pointeur, c’est un pointeur de structure.

EDIT:

C’est bon, j’étais sur la bonne piste. C’est comme les tableaux, c’est pas un membre de la structure auquel le pointeur fait allusion dans ce cas mais à la structure en elle-même. J’ai tout bon ?

+0 -0

Je ne pense pas que ce soit ça. Ça aurait été la même chose si on avait passé un double pointeur d’entier.

Tu devrais peut-être revoir un cours sur les pointeurs. C’est une notion un peu difficile mais importante.

Il y a un bon cours sur le langage C sur le site, je te redirige directement vers la partie Pointeurs

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte