TTF_CloseFont()分段错误

时间:2016-09-15 17:27:58

标签: c++ sdl

当调用析构函数Text :: ~Text()并且我不知道为什么时,我得到了段错误。
这是代码:

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

1 个答案:

答案 0 :(得分:0)

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

但是您没有定义自定义复制构造函数。因此,如果您的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也非常难以阅读。使用名称来说明函数究竟会做什么。