TTF_RenderText_Solid(...)导致分段错误错误

时间:2020-05-28 13:38:13

标签: c++ codeblocks sdl-2 sdl-ttf

我正在尝试利用类Text处理基于c ++ SDL2的程序中的文本。

TTF_RenderText_Solid在main函数中可以很好地工作,尽管在我的类Text的{​​{1}}这行中,这会导致一些错误。有时它给我一个细分错误,有时却没有。

我调试了代码,SDL_Surface *surface = TTF_RenderText_Solid( font, text.c_str(), fg );TTF_Font *fontstd::string text这三个变量分别具有正确的值。

我的主要功能:

SDL_Color fg

我的#include <iostream> #include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> #include "Text.h" int main() { try { SDL_Init( SDL_INIT_VIDEO ); TTF_Init(); SDL_Window *window = SDL_CreateWindow( "Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 800, SDL_WINDOW_SHOWN ); SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED ); TTF_Font *f = TTF_OpenFont( "cruft.ttf", 32 ); SDL_Surface *s = TTF_RenderText_Solid( f, "Avocado", {0,0,0,255} ); if(s == NULL) std::cout << "s == NULL\n"; Text title; title = Text( renderer, "cruft.ttf", 32, "title" ); title.render_Text_Solid( "Avocado", {0,0,0,255} ); SDL_Quit(); TTF_Quit(); return 0; } catch( std::exception& e ) { std::cerr << "Error: " << e.what() << "\n"; return 0; } catch(...) { std::cerr << "Unkown error!\n"; return 0; } } 文件:

Text.cpp

我的#include <iostream> #include <string.h> #include "Text.h" #include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> //Constructors Text::Text(){} Text::Text(SDL_Renderer *renderer, std::string file, int ptsize, std::string name) { set_renderer( renderer ); this->name = name; set_TTF_Font( file, ptsize ); } Text::~Text() { TTF_CloseFont( font ); SDL_DestroyTexture( texture ); } void Text::set_renderer( SDL_Renderer *renderer ) { if( renderer == NULL ) throw std::runtime_error( name + ": Renderer could not be set! renderer == NULL\n" + SDL_GetError() ); this->renderer = renderer; } void Text::set_TTF_Font( std::string file, int ptsize ) { TTF_CloseFont( font ); font = NULL; SDL_DestroyTexture( texture ); texture = NULL; width = 0; height = 0; if( file == "" ) throw std::runtime_error( name + ": TTF_Font* could not be set! file == ""\n" + SDL_GetError() ); if( ptsize <= 0 ) throw std::runtime_error( name + ": TTF_Font* could not be set! ptsize <= 0\n" + SDL_GetError() ); TTF_Font *font = TTF_OpenFont( file.c_str(), ptsize ); if( font == NULL ) throw std::runtime_error( name + ": TTF_Font* could not be set! font == NULL\n" + SDL_GetError() ); this->font = font; } void Text::render_Text_Solid( std::string text, SDL_Color fg ) { SDL_DestroyTexture( texture ); texture = NULL; width = 0; height = 0; SDL_Surface *surface = TTF_RenderText_Solid( font, text.c_str(), fg ); if( surface == NULL ) throw std::runtime_error( name + ": Text could not be created! surface == NULL\n" + SDL_GetError() ); texture = SDL_CreateTextureFromSurface( renderer, surface ); width = surface->w; height = surface->h; SDL_FreeSurface( surface ); if( texture == NULL ) throw std::runtime_error( name + ": Text could not be created! texture == NULL\n" + SDL_GetError() ); } 文件:

Text.h

PS:我使用的是Manjaro Linux和代码块

1 个答案:

答案 0 :(得分:2)

让我们首先看看这些行的作用:

    Text title;
    title = Text( renderer, "cruft.ttf", 32, "title" );

首先,您创建title,并使用默认构造函数Text::Text()对其进行初始化,该构造函数将默认值设置为其字段。然后,使用专门的构造函数创建第二个Text(为清楚起见,我们将其称为title1)对象。然后将title1复制到title-由于未定义operator=,因此会生成默认副本。现在,您的title具有与title1相同的值。然后title1.~Text()被调用,杀死您的font

您拥有的title.font仍然具有其先前的值,但是它指向已经关闭的字体结构。

可以通过不构造临时Text对象来避免-例如Text title = Text(.......)将不会产生临时对象和复制。那只是一种解决方法,实际问题仍然存在-无法安全地复制Text对象。解决此问题的方法有很多,例如使用某种unique_ptr包装器或丢弃析构函数以使用手动deinit方法等。

这给我们带来了下一个问题-如果您解决了复制问题,现在可以生成文本表面和纹理,但是请查看退出代码:

    Text title;
    // ... omitted
    SDL_Quit();
    TTF_Quit();
    return 0;

您需要以相反的方式完成终结工作-您想要关闭字体,删除纹理,销毁渲染器/窗口,然后分别调用TTF_QuitSDL_Quit,但是您拥有{ {1}},SDL_Quit()以及之后的TTF_Quit()可能会崩溃,因为SDL / TTF已经完成,并且您不应该在那之后执行SDL调用。当然也可以解决,例如通过将title.~Text()放入额外的代码块中,但需要注意的事情变得太大了。

相关问题