2017-04-04 122 views
0

我正在试图制作一个程序来移动一个基于键盘输入的盒子,但目前它只设置为在屏幕上呈现一个绿色的矩形。但是,程序似乎是初始化窗口,然后在终止之前返回“分段错误(核心转储)”。我根本没有得到任何编译器错误,并且一小部分代码与我在网上找到的教程相匹配。如果它有所作为,我使用GCC在Ubuntu上运行Code :: Blocks。SDL2分割错误

main基本上调用函数称为initdrawRectclose以该顺序(所有如下所示),基于成功或失败的打印语句。

编辑:缩小到close,如下所示。特别是,SDL_FreeSurface和SDL_Quit给我提供了一些问题。我还清理了关闭指针处理(和程序的其他部分)并创建了一个新的pastebin文件。

接近:

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(); 
} 

这里的满源代码,完成指针的初始化,包括和伪代码:

/* === 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

在启用额外警告的情况下构建,并在出现任何问题时进行修复。并用调试信息构建,并在调试器中运行以捕捉崩溃,以确定发生的位置。 –

+0

你们都需要一些RAII。 – jaggedSpire

+0

你是先测试这个例子吗? https://wiki.libsdl.org/SDL_CreateWindow – Rama

回答

1

你通过传递SDL_Renderer *renderer指针您drawRect功能值,并在该函数中初始化它。这并不是初始化你在全局范围内的指针,而是在你退出函数时丢失了它的副本。然后你在close上调用SDL_DestroyRenderer来自全局作用域的指针,即NULL

如果要初始化drawRect函数中的全局函数,则需要将指针传递给该函数(SDL_Renderer **)。

在你drawRect功能你打电话SDL_RenderDrawRect,这是绘制矩形到后缓冲区,以再画,你需要使用一个电话SDL_RenderPresent

+0

这可能至少是我的问题的一部分。不幸的是,我现在有更多。 (我生命的故事tbh。) –

0

不要试图释放在屏幕上从SDL_GetWindowSurface()返回表面,SDL管理返回的指针本身的寿命:

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

查看的文档为SDL_GetWindowSurface()(重点煤矿):

备注

如有必要,将为窗口创建一个新的曲面,使其具有最佳格式。窗口被销毁时,这个表面将被释放。 不要释放这个表面。