SDL_BlitSurface引发分段错误错误

时间:2018-07-19 15:03:58

标签: c++ sdl sdl-2

我正在尝试使用Menu类显示菜单。但是在该类的函数draw()中,SDL_BlitSurface不起作用,并且在执行以下行时抛出了默认的分段:

SDL_BlitSurface(el.surfaceNormal, NULL, surface, &el.rect); 

以下是该函数的代码:

void Menu::draw(SDL_Surface* surface) {
    for(int i=0; i<menuElementList.size(); i++){
        auto el = menuElementList.at(i);
        SDL_BlitSurface(el.surfaceNormal, NULL, surface, &el.rect); 
    }
}

我在vector中使用的结构:

struct menuElement{
    SDL_Surface* surfaceNormal;
    SDL_Surface* surfaceHover;
    SDL_Rect rect;
    std::string text;
};

通常,我应该能够渲染矢量中存在的所有表面,但是由于我无法弄清楚它不起作用的原因。

填充矢量的代码:

void Menu::addMenu(std::string name, int x, int y) {
    menuElement m;
    TTF_Font* Sans = TTF_OpenFont("OpenSans-Light.ttf", 25); 
    if(!Sans){
        std::cout << TTF_GetError() << std::endl;
    }
    SDL_Color White = {255, 255, 255};  
    SDL_Surface* surfaceMessage = TTF_RenderText_Solid(Sans, name.c_str(), White); 
    m.surfaceNormal = surfaceMessage;    
    SDL_Color Red = {255, 0, 0}; 
    SDL_Surface* hoverMessage = TTF_RenderText_Solid(Sans, name.c_str(), Red);
    m.surfaceHover = hoverMessage;
    SDL_Rect rect;
    rect.x = rect.y = 50;
    m.rect = rect;
    m.text = name;
    SDL_FreeSurface(surfaceMessage);
    SDL_FreeSurface(hoverMessage);
    menuElementList.push_back(m);
}

我知道填充了向量,因为我可以显示其中每个元素的text属性。怎么了?

1 个答案:

答案 0 :(得分:1)

如果调试了一下,错误就会很简单,这是您应该做的MVCE。

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <iostream>
#include <vector>
#include <string>

#define HEIGHT 600
#define WIDTH  800

using namespace std;

struct menuElement{
    SDL_Surface* surfaceNormal;
    SDL_Surface* surfaceHover;
    SDL_Rect rect;
    std::string text;
};

std::vector<menuElement> menuElementList;

void add_element(std::string name, int x, int y) {
    menuElement m;
    TTF_Font* Sans = TTF_OpenFont("OpenSans-Light.ttf", 25);
    if(!Sans){
        std::cout << TTF_GetError() << std::endl;
    }
    SDL_Color White = {255, 255, 255};
    SDL_Surface* surfaceMessage = TTF_RenderText_Solid(Sans, name.c_str(), White);
    m.surfaceNormal = surfaceMessage;
    SDL_Color Red = {255, 0, 0};
    SDL_Surface* hoverMessage = TTF_RenderText_Solid(Sans, name.c_str(), Red);
    m.surfaceHover = hoverMessage;
    SDL_Rect rect{x, y, 50, 50};  // You were never using x and y before now it draws at that position with a rect of size 50x50
    m.rect = rect;
    m.text = name;
  //  SDL_FreeSurface(surfaceMessage); << how is this not crashing in your system when blitting, I don't know
  //  SDL_FreeSurface(hoverMessage);
    menuElementList.push_back(m);
}

int main() {
    SDL_Init(SDL_INIT_VIDEO);

    TTF_Init();
    SDL_Window *window = SDL_CreateWindow("TextFail", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);

    SDL_Surface *surface = SDL_GetWindowSurface(window);
    bool quit = false;
    SDL_Event event;

    add_element("ello", 20, 20);
    add_element("Bye", 40, 40);


    while (!quit) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                quit = true;
            }
        }

        for (auto &el : menuElementList)
            SDL_BlitSurface(el.surfaceNormal, NULL, surface, &el.rect);

        SDL_UpdateWindowSurface(window);
    }

    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

我评论了困扰您的两行内容,即使向量已经填充,因为自从释放表面以来,填充了未初始化的数据,也应该在释放menuElement时执行此操作(如果您在menuElement中使用C ++例如,析构函数或在free_menu_element(menuElement * e){..}函数(如果为C)上

请记住,当您复制指针时,您复制的是它们指向的内存方向,而不是其内容。

您也从未使用过x和y!