2017-04-04 1 views
0

J'essaye de faire un programme pour déplacer une boîte basée sur l'entrée de clavier, mais pour le moment il est seulement configuré pour rendre un rectangle vert sur l'écran. Cependant, le programme semble initialiser la fenêtre, puis ne renvoie rien de plus que "Erreur de segmentation (core dumped)" avant de se terminer. Je n'ai aucune erreur de compilation, et une bonne partie du code correspond aux tutoriels que j'ai trouvés en ligne. Si cela fait une différence, je cours Code :: Blocks sur Ubuntu en utilisant GCC.SDL2 Segmentation Fault

main appelle essentiellement les fonctions appelées init, drawRect et close (tous indiqués ci-dessous) dans cet ordre, les déclarations d'impression en fonction du succès ou de l'échec.

EDIT: Réduit à close, illustré ci-dessous. En particulier, c'est SDL_FreeSurface et SDL_Quit qui me posent des problèmes. J'ai également nettoyé à proximité (et d'autres parties du programme) en ce qui concerne la gestion du pointeur et fait un nouveau fichier pastebin.

près:

void close() 
{ 
    // Deallocate gScreenSurface 
    SDL_FreeSurface(gScreenSurface); 
    gScreenSurface=NULL; 

    // Destroy renderer 
    SDL_DestroyRenderer(gRenderer); 
    gRenderer=NULL; 

    // Destroy gWindow 
    SDL_DestroyWindow(gWindow); 
    gWindow=NULL; 

    SDL_Quit(); 
} 

Voici le nouvelle sourcecode complète, avec initialisations pointeur, comprend et pseudocode:

/* === Includes === */ 
#include <cstdlib> 
#include <stdio.h> 
#include "SDL2/SDL.h" 

using namespace std; 

/* === Constants === */ 
const int SCREEN_WIDTH = 640; 
const int SCREEN_HEIGHT = 480; 

/* === Enums === */ 
/*enum Keys {KEY_DEFAULT, 
      KEY_UP, 
      KEY_DOWN, 
      KEY_LEFT, 
      KEY_RIGHT, 
      KEY_TOTAL};*/ 

/* === Prototypes === */ 

bool init(); 
bool drawRect(SDL_Renderer* pRenderer, SDL_Rect* pRect, int pX, int pY, int pW, int pH, int pR, int pG, int pB, int pA); 
void close(); 

/* === Pointer Initialization === */ 
SDL_Window* gWindow = NULL; 
SDL_Surface* gScreenSurface = NULL; 
SDL_Renderer* gRenderer = NULL; 
SDL_Rect* gRect = NULL; 

/**================================================== 
Box Mover 

This was intended to be a learning activity to 
teach myself how to use SDL, in particular basic 
"block" graphics and keyboard inputs. 

Unfortunately, I can't figure out why it's always 
returning seg fault. I think it's outside of main, 
but I can't be sure. 
==================================================**/ 

int main() 
{ 
    if(!init()) 
     printf("Failed to initialize!\n"); 
    else 
    { 
     if(!drawRect(gRenderer, gRect, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 255, 0, 255)) 
     printf("Failed to draw rectangle!\n"); 
     else 
     { 
     /*SDL_BlitSurface(gImage, NULL, gScreenSurface, NULL); 
     SDL_UpdateWindowSurface(gWindow); 
     SDL_Delay(2000);*/ 
     printf("Success in main!\n"); // Placeholder until I figure out why I'm getting a seg fault, then I can fix the contents. 
     } 
    } 
    close(); 

    return 0; 
} 

/*========================= 
Init 

Initializes SDL 
Returns true for success, false for failure 
Prints error on failure 
=========================*/ 
bool init() 
{ 
    //Initialization flag 
    bool success = true; 
    if(SDL_Init(SDL_INIT_VIDEO) < 0) 
    { 
     printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); 
     success = false; 
    } 
    else 
    { 
     gWindow = SDL_CreateWindow("Box Mover", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0); 
     if(gWindow == NULL) 
     { 
     printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); 
     success = false; 
     } 
     else 
     { 
     gScreenSurface = SDL_GetWindowSurface(gWindow); 
     } 
    } 
    return success; 
} 

/*========================= 
Draw Rectangle 

Draws a rectangle of specified color and location 

TO DO: 
Check to see if renderer needs to be deallocated here. 

Inputs: 
>> pRenderer:  SDL_Renderer pointer which can be thought of as a drawing tool 
>> pRect:   SDL_Rect pointer which holds location and size data 
>> pX, pY:  X-Y location of the upper left corner of the rectangle 
>> pR, pG, pB: Color values (technically Uint8, 0-255) 
>> pA:   Alpha (transparency) value of the rectangle (also technically Uint8) 
=========================*/ 
bool drawRect(SDL_Renderer* pRenderer, SDL_Rect* pRect, int x, int y, int w, int h, int r, int g, int b, int a) 
{ 
    bool success = true; 

    pRenderer=SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_SOFTWARE); 
    if(pRenderer==NULL) 
    { 
     printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError()); 
     success=false; 
    } 
    else 
    { 
     pRect = new SDL_Rect; 
     if(pRect == NULL) 
     { 
     printf("Could not create rectangle! SDL Error: %s\n", SDL_GetError()); 
     success=false; 
     } 
     else 
     { 
      pRect->x = x; 
      pRect->y = y; 
      pRect->w = w; 
      pRect->h = h; 

     SDL_SetRenderDrawColor(pRenderer, r, g, b, a); 

     if(SDL_RenderDrawRect(pRenderer, pRect) < 0) 
     { 
      printf("Rectangle could not be rendered! SDL Error: %s\n", SDL_GetError()); 
      success=false; 
     } 
     } 
    } 
    return success; 
} 

/*========================= 
Close 

Closes the SDL systems cleanly, deallocating memory. 

Found the seg fault! It's this fucker! 
In particular, SDL_FreeSurface and SDL_Quit 
=========================*/ 
void close() 
{ 
    // Deallocate gScreenSurface 
    SDL_FreeSurface(gScreenSurface); 
    gScreenSurface=NULL; 
    printf("Surface closed. Working on renderer...\n"); 

    // Destroy renderer 
    SDL_DestroyRenderer(gRenderer); 
    gRenderer=NULL; 
    printf("Renderer closed. Working on window...\n"); 

    // Destroy gWindow 
    SDL_DestroyWindow(gWindow); 
    gWindow=NULL; 
    printf("Window closed. Working on SDL...\n"); 

    SDL_Quit(); 
    printf("SDL closed.\n"); 
} 
+4

Construire avec des avertissements supplémentaires activés, et les réparer si vous en avez. Et construire avec des informations de débogage, et exécuter dans un débogueur pour attraper le plantage dans l'action pour localiser où cela se produit. –

+0

Vous avez besoin de RAII dans votre vie. – jaggedSpire

+0

Avez-vous testé cet exemple en premier? https://wiki.libsdl.org/SDL_CreateWindow – Rama

Répondre

1

vous passez le pointeur SDL_Renderer *renderer à votre fonction drawRect par valeur, et l'initialiser dans cette fonction. Cela n'initialise pas le pointeur que vous avez dans la portée globale, il en initie une copie qui est perdue lorsque vous quittez la fonction. Vous êtes alors dans close appelant SDL_DestroyRenderer sur le pointeur de portée globale, qui est NULL.

Si vous souhaitez initialiser le global à l'intérieur de votre fonction drawRect, vous devez passer un pointeur vers un pointeur (SDL_Renderer **) à la fonction.

Dans votre fonction drawRect que vous appelez SDL_RenderDrawRect, c'est rendu le rectangle sur un tampon arrière, pour tirer ensuite sur l'écran, vous devez utiliser un appel à SDL_RenderPresent

+0

C'était probablement au moins une partie de mon problème. Malheureusement, j'en ai maintenant plus. (Histoire de ma vie tbh.) –

0

Ne pas essayer de libérer le surface de retour SDL_GetWindowSurface(), SDL gère la durée de vie du pointeur de retour lui-même:

gScreenSurface = SDL_GetWindowSurface(gWindow); 
... 
SDL_FreeSurface(gScreenSurface); 

Voir la documentation pour SDL_GetWindowSurface() (Souligné par l'auteur):

Remarques

Une nouvelle surface sera créée avec le format optimal pour la fenêtre, si nécessaire. Cette surface sera libérée lorsque la fenêtre sera détruite. Ne pas libérer cette surface.