C++ 字体呈现函数C+;中未处理的异常+;SDL

C++ 字体呈现函数C+;中未处理的异常+;SDL,c++,class,exception,sdl,C++,Class,Exception,Sdl,我正在制作一个乒乓球克隆,就在标题屏幕上。我有一个类来处理状态机的标题屏幕循环,它使用的很少,只有一个sprite和一个true-type字体消息。但当我调用函数将消息渲染到SDL_曲面上时,它会使我的程序陷入混乱。我收到的错误是Pong.exe中0x6F4C2A9D(SDL_ttf.dll)处的未处理异常:0xC0000005:访问冲突读取位置0x00000000。通常这意味着我没有初始化某个对象,或者没有在类定义或某个对象中定义它,但看起来一切正常。因此,我将在这里发布代码,希望有人能看到渲

我正在制作一个乒乓球克隆,就在标题屏幕上。我有一个类来处理状态机的标题屏幕循环,它使用的很少,只有一个sprite和一个true-type字体消息。但当我调用函数将消息渲染到SDL_曲面上时,它会使我的程序陷入混乱。我收到的错误是Pong.exe中0x6F4C2A9D(SDL_ttf.dll)处的
未处理异常:0xC0000005:访问冲突读取位置0x00000000。
通常这意味着我没有初始化某个对象,或者没有在类定义或某个对象中定义它,但看起来一切正常。因此,我将在这里发布代码,希望有人能看到渲染函数或其周围的位是怎么回事

为了清楚起见,在这一行上抛出异常:

Title\u Message=TTF\u RenderText\u实体(字体,“PONG”,颜色)

//start code
/*CLASSES*/

class GameState
{
public:
    virtual void events() = 0;
    virtual void logic() = 0;
    virtual void render() = 0;
    virtual ~GameState(){};
};

class Button
{
public:
    SDL_Rect button_clip[2];
    SDL_Rect button;
    SDL_Surface *button_sprite = NULL;
    Button();
};

class Title : public GameState
{
private:
    SDL_Surface *Title_Message = NULL;
    SDL_Rect *clip;
    Button Title_Button;
public:
    void events();
    void logic();
    void render();
    Title();
    ~Title();
};

/*FONTS*/
SDL_Color color = { 255, 255, 255 };
TTF_Font *font = NULL;

bool init()
{
    //initialize all SDL subsystems
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
    {
        return false;
    }
    //set up screen
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
    //check screen
    if (screen == NULL)
    {
        return false;
    }
    //init TTF
    if (TTF_Init() == -1)
    {
        return false;
    }
    //set window caption
    SDL_WM_SetCaption("PONG", NULL);
    //if evetything worked
    return true;
}

//load files
bool load_files()
{
    font = TTF_OpenFont("PIXELITE.ttf", 45);
    if (font == NULL)
    {
        return false;
    }
    return true;
}

/*CLASS DEFINITIONS*/

Button::Button()
{

}

Title::Title()
{
    Title_Message = TTF_RenderText_Solid(font, "PONG", color);
    Title_Button.button_sprite = load_image("Start.png");
    Title_Button.button.x = 200;
    Title_Button.button.y = 350;
    Title_Button.button.w = 100;
    Title_Button.button.h = 50;
    //clips not hover
    Title_Button.button_clip[0].x = 0;
    Title_Button.button_clip[0].y = 0;
    Title_Button.button_clip[0].w = 100;
    Title_Button.button_clip[0].h = 50;
    //clips hover
    Title_Button.button_clip[1].x = 0;
    Title_Button.button_clip[1].y = 50;
    Title_Button.button_clip[1].w = 100;
    Title_Button.button_clip[1].h = 50;
}

Title::~Title()
{
    SDL_FreeSurface(Title_Message);
    SDL_FreeSurface(Title_Button.button_sprite);
}

void Title::events()
{
    int x = 0;
    int y = 0;
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_MOUSEMOTION)
        {
            x = event.motion.x;
            y = event.motion.y;
            if ((x > Title_Button.button.x) && (x < (Title_Button.button.x + Title_Button.button.w)) && (y > Title_Button.button.y) && (y < (Title_Button.button.y + Title_Button.button.h)))
            {
                clip = &Title_Button.button_clip[1];
            }
            else
            {
                clip = &Title_Button.button_clip[0];
            }
        }
        if (event.type == SDL_QUIT)
        {
            quit = true;
        }
    }
}

void Title::logic()
{

}

void Title::render()
{
    apply_surface(Title_Button.button.x, Title_Button.button.y, Title_Button.button_sprite, screen, clip);
    apply_surface((SCREEN_WIDTH - Title_Message->w) / 2, 100, Title_Message, screen);
}
//开始代码
/*班级*/
类配子态
{
公众:
虚空事件()=0;
虚空逻辑()=0;
虚拟void render()=0;
虚拟~GameState(){};
};
类按钮
{
公众:
SDL_-Rect按钮_-clip[2];
SDL__Rect按钮;
SDL_表面*按钮_精灵=NULL;
按钮();
};
课程名称:公共游戏状态
{
私人:
SDL_Surface*Title_Message=NULL;
SDL_Rect*剪辑;
按钮标题\按钮;
公众:
无效事件();
无效逻辑();
void render();
Title();
~Title();
};
/*字体*/
SDL_颜色={255,255,255};
TTF_Font*Font=NULL;
boolinit()
{
//初始化所有SDL子系统
if(SDL_Init(SDL_Init_EVERYTHING)=-1)
{
返回false;
}
//设置屏幕
屏幕=SDL_设置视频模式(屏幕宽度、屏幕高度、屏幕BPP、SDL_表面);
//检查屏幕
如果(屏幕==NULL)
{
返回false;
}
//初始TTF
如果(TTF_Init()=-1)
{
返回false;
}
//设置窗口标题
SDL_WM_SetCaption(“PONG”,空);
//如果一切都有效的话
返回true;
}
//加载文件
bool load_文件()
{
font=TTF_OpenFont(“PIXELITE.TTF”,45);
如果(字体==NULL)
{
返回false;
}
返回true;
}
/*类定义*/
按钮::按钮()
{
}
Title::Title()
{
Title_Message=TTF_RenderText_Solid(字体,“PONG”,颜色);
Title_Button.Button_sprite=load_图像(“Start.png”);
Title_Button.Button.x=200;
Title_Button.Button.y=350;
标题按钮w=100;
Title_Button.Button.h=50;
//剪辑不悬停
标题按钮。按钮剪辑[0]。x=0;
标题按钮。按钮剪辑[0]。y=0;
标题按钮。按钮剪辑[0]。w=100;
标题按钮。按钮剪辑[0]。h=50;
//剪辑悬停
标题按钮。按钮剪辑[1]。x=0;
标题按钮。按钮夹[1]。y=50;
标题按钮。按钮夹[1]。w=100;
标题按钮。按钮夹[1]。h=50;
}
标题::~Title()
{
SDL_自由曲面(标题信息);
SDL_自由曲面(标题_按钮。按钮_精灵);
}
void Title::events()
{
int x=0;
int y=0;
while(SDL_事件和事件))
{
if(event.type==SDL\u)
{
x=event.motion.x;
y=event.motion.y;
如果((x>Title_Button.Button.x)和&(x<(Title_Button.Button.x+Title_Button.Button.w))&(y>Title_Button.Button.y)和&(y<(Title_Button.Button.y+Title_Button.Button.h)))
{
剪辑=&标题按钮。按钮剪辑[1];
}
其他的
{
剪辑=&标题按钮。按钮剪辑[0];
}
}
if(event.type==SDL\u QUIT)
{
退出=真;
}
}
}
void Title::logic()
{
}
void Title::render()
{
应用_表面(Title_按钮.Button.x,Title_按钮.Button.y,Title_按钮.Button_精灵,屏幕,剪辑);
应用曲面((屏幕宽度-标题消息->w)/2100,标题消息,屏幕);
}

有人有主意吗?谢谢

我将从评论中发布我的建议作为实际答案:

引起故障的行
Title\u Message=TTF\u RenderText\u Solid(字体,“PONG”,颜色)
指类型为
TTF\u font*
的全局变量
font
。该行也是类
Title
的构造函数的一部分

main
如下所示:

int main(int argc, char* args[])
{
    //init SDL
    init();
    //load everything
    load_files();
    currentState = new Title;
    //...
font
在声明时初始化为
NULL
,实际对象仅在
load_files()
中分配,该对象在
main
的开头执行,然后
Title
第一次实例化

因此
load_files()
必须为
font
分配一个有效指针,否则
main
中的下一行将导致访问冲突

load_files()
根据创建和分配此对象是否成功提供返回值。但是,
main
从不检查此值,因此不能保证
font
是有效的指针


正如knefcy指出的,问题在于
load_files()

中的文件名错误,代码示例太复杂了。将其减少到最小值,但仍显示错误。这就是说:您有多个init函数,它们可能返回
true
false
,具体取决于初始化成功与否,但您从未实际检查
main
中的返回值。你怎么知道
init()
load_files()
中的初始化成功了?其实行数不多,但我可以看到我能做什么。它们成功的原因是,在添加TTF渲染行之前,程序编译并运行得很好。不过我可以检查它们。我问的原因是因为
font
仅由引起故障的行使用,并在
load\u files()
中初始化。哦,我找到了,字体文件是.FON而不是.TTF。不过谢谢你。sdl+字体问题通常都是这样。