2016-09-15 64 views
0

当析构函数Text ::〜Text()被调用时,我得到一个段错误,我不知道为什么。
下面的代码:
TTF_CloseFont()分段错误

class Texture 
{ 
    protected: 
     SDL_Texture* value = NULL; 
     SDL_Rect info; 
     Window* window = NULL; 
    public: 
     void assign(SDL_Surface* surface) 
     { 
      //Free current texture 
      SDL_DestroyTexture(value); 

      //Create the texture 
      value = SDL_CreateTextureFromSurface(window->getRenderer(),surface); 
      info.x=0, info.y=0, info.w=surface->w, info.h=surface->h; 
      if (!value) 
      { 
       cout << "Failed to load texture from surface: " << SDL_GetError() << endl; 
      } 
     } 
     void assign(const char* filename) 
     { 
      //Free current texture 
      SDL_DestroyTexture(value); 

      //Create the texture 
      SDL_Surface* temp = IMG_Load(filename); 
      if (!temp) 
      { 
       cout << "Failed to load texture \"" << filename << "\": " << IMG_GetError() << endl; 
       return; 
      } 
      value = SDL_CreateTextureFromSurface(window->getRenderer(),temp); 
      if (!value) 
      { 
       cout << "Failed to load texture \"" << filename << "\": " << SDL_GetError() << endl; 
       return; 
      } 
      info.x=0, info.y=0, info.w=temp->w, info.h=temp->h; 
     } 
     void assign(Window& newWindow) { window = &newWindow; } 
     void render(const int x, const int y) 
     { 
      //Check if there is a texture 
      if (!value) 
      { 
       cout << "Failed to render texture: empty!" << endl; 
       return; 
      } 
      //Create temporary location info 
      SDL_Rect temp; 
      temp.x=x, temp.y=y, temp.w=info.w, temp.h=info.h; 
      //Render 
      SDL_RenderCopy(window->getRenderer(), value, &info, &temp); 
     } 
     void render(const int x, const int y, const int renderX, const int renderY, const int renderW, const int renderH) 
     { 
      //Create temporary location info 
      SDL_Rect temp; 
      temp.x=x, temp.y=y, temp.w=renderW, temp.h=renderH; 
      //Create temporary info to cut off part of the image 
      SDL_Rect temp2; 
      temp2.x=renderX, temp2.y=renderY, temp2.w=renderW, temp2.h=renderH; 
      //Render 
      SDL_RenderCopy(window->getRenderer(), value, &temp2, &temp); 
     } 
     int getW() { return info.w; } 
     int getH() { return info.h; } 

     Texture() {} 
     Texture(Window& window, const char* filename) 
     { 
      assign(window); 
      assign(filename); 
     } 
     virtual ~Texture() { SDL_DestroyTexture(value); } 
}; 

class Text 
{ 
    private: 
     char* value = NULL; 
     int size; 
     TTF_Font* font = NULL; 
    public: 
     Texture texture; 

     void assign(const int r, const int g, const int b, const int a, const char* text) 
     { 
      //Assign text to value 
      value = const_cast<char*>(text); 

      //Render the texture 
      SDL_Color color; color.r=r, color.g=g, color.b=b, color.a=a; 
      texture.assign(TTF_RenderText_Solid(font, const_cast<char*>(text), color)); 

      //Check if successful 
      if (!font) 
      { 
       cout << "Failed to render text \"" << text << "\": " << TTF_GetError() << endl; 
      } 
     } 
     void assign(const int newSize, const char* newFont) 
     { 
      size=newSize, font=TTF_OpenFont(newFont,newSize); 
      if (!font) 
      { 
       cout << "Failed to open font \"" << newFont << "\":" << TTF_GetError() << endl; 
      } 
     } 

     Text() {} 
     Text(Window& window, const int size, const char* font, const char* text, const int r = 0, const int g = 0, const int b = 0, const int a = 0)   { 
      texture.assign(window); 
      assign(size,font); 
      assign(r,g,b,a,text); 
     } 
     virtual ~Text() { TTF_CloseFont(font); } 
}; 

class fpsTimer : public Text 
{ 
    private: 
     int frames{}; 
    public: 
     void update() 
     { 
      ++frames; 
      stringstream buffer; 
      if (SDL_GetTicks()>1000) 
      { 
       buffer << frames/(SDL_GetTicks()/1000); 
       assign(255,128,0,0,buffer.str().c_str()); 
      } 
      else 
      { 
       assign(255,128,0,0,"0"); 
      } 
     } 
     int updateFrames() { ++frames; } 
     int getFPS() { if (SDL_GetTicks()>1000) return frames/(SDL_GetTicks()/1000); else return 0; } 

     fpsTimer() {} 
     fpsTimer(Window& window, const int size, const char* font) : Text(window,size,font,"0",255,128,0,0) {} 
}; 
+0

有时需要编译并在调试模式下运行 – Flint

回答

0

Text类处理一个的ressource,字体,并定义了关闭字体自定义的析构函数。

但是你没有定义一个自定义的拷贝构造函数。因此,如果您的Text实例的字体为非NULL并且实例被复制,则您现在有两个Text实例,这两个实例在关闭销毁时都会关闭相同的字体。我不确定是否允许关闭两次相同的字体,但无论如何,在第一次销毁之后,字体可能不会再被使用。

定义自定义副本构造函数(和复制赋值运算符),确定如何处理副本上字体的所有权,或者如果您不想允许副本,则删除隐式声明的副本构造函数。见Rule of three

对于C++ 11,请使用移动构造函数和移动赋值运算符,请参阅“五个规则”。

您与Texture课程有同样的问题。

而且这里:

assign(size,font); 
assign(r,g,b,a,text); 

如果第一assign产生错误信息,font仍然NULL,但在第二assign您呼叫TTF_RenderText_Solid用它,这是不允许的,并会产生分段错误。

调用您的所有成员函数assign也非常难以阅读。使用名称来说明函数的功能。