SDL_BlitSurface 抛出分段错误

SDL_BlitSurface is throwing segmentation fault error

我正在尝试使用菜单 class 显示菜单。但是在 class 的函数 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); 
    }
}

我在向量中使用的结构:

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

我知道矢量会被填充,因为我可以显示其中每个元素的文本属性。怎么了?

好吧,这个错误非常简单,如果稍微调试一下你就会意识到,这是你应该完成的 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;
}

我评论了让你感到困惑的 2 行,即使矢量被填充它也被未初始化的数据填充,因为你释放了表面,你应该在释放 menuElement 时这样做(如果你在例如 menuElement 析构函数或 free_menu_element(menuElement *e) { .. } 函数 if C)

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

您也从未使用过 x 和 y!