为什么当我从初始化函数 return 时我的 SDL window 关闭?

Why does my SDL window close when i return from an initializing function?

我一直在研究一个简单的游戏引擎(我知道,我知道,我以前听说过 "Write games not engines",这只是为了理解概念)。我一直在使用 SDL2,因为它与 OpenGL 配合得很好。但是由于某些原因,程序会在初始化功能完成后关闭。

Screen.cpp:
Screen::Screen(int width, int height, const std::string& title)
    {

        //Initialize SDL
        SDL_Init(SDL_INIT_EVERYTHING);
        //Setting OpenGL Attributes
        SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

        //Create the Window
        m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
        l.writeToDebugLog("Created SDL_Window!");
        //Create OpenGL context from within SDL
        m_glContext = SDL_GL_CreateContext(m_window);
        l.writeToDebugLog("Created SDL GL Context!");

        //Initializing GLEW
        GLenum status = glewInit();
        l.writeToDebugLog( "Initializing GLEW");
        if (status != GLEW_OK)
        {
                l.writeToGLEWELog(" Glew Failed to Initialize!");
        }

        //setting the windowSurface to the m_window's surface
        windowSurface = SDL_GetWindowSurface(m_window);
        m_isClosed = false;
    }

这是我创建屏幕对象并初始化所有 SDL 函数和 OpenGL 函数的地方

Engine.cpp:
        void Engine::initialize(){

        //Console Detecting platform
        c.initialize();
        //Printing Operating System to screen
        std::cout << "Loaded on : " << platformToString(c.os) << " OS " << std::endl;
        //Constructing a new Screen to be referenced too
        graphics::Screen temp(800,600,"ClimLib 0.0.05"); 

        //setting all the variables
        m_window = &temp;
        m_EntityManager = nullptr;
        m_isRunning = temp.isClosed();
        m_renderer = SDL_GetRenderer(m_window->getWindow());


    }
    void Engine::update(){
        do{
            //Check whether entities have been created and placed in the manager
            if (m_EntityManager != nullptr){
                for each(core::Entity *e in *m_EntityManager){
                    for each(core::Component *c in e->getComponentList()){
                        c->Update();
                    }
                }
            }


            //Update Logic Here
            m_window->Update();
            if (m_window->isClosed()){
                m_isRunning = false;
                return;
            }

            }while (isRunning());
        } 

这个初始化函数是我的 window 在删除自身之前执行的最后一个函数,也许我需要从程序的主函数调用它?

main.cpp:
int main(int argc, char *argv[]){
    clim::system::Engine game;
game.initialize();
while (game.isRunning()){
    game.update();
    }
return 0;
}

这就是我目前的主要设置方式。

编辑: 我相信原因是因为我正在创建一个变量并将其存储为参考,当函数 returns 临时变量被丢弃时?

您将屏幕创建为一个临时值,然后将该值的地址分配给一个指针,该指针的生命周期实际上超过了它所指向的值的生命周期,它很可能也是一个堆栈值。如果 window 快要死了,这将导致您在以后使用时出现以下一种或两种情况:

  • 崩溃(非法内存访问)
  • 未定义的行为(从读取堆栈中位于此地址的随机值稍后执行)

虽然现在可能不适用,但这确实是一个让你自己在几乎所有事情上都头疼的好方法。

你应该像这样赋值:

 m_window = new graphics::Screen(800,600,"ClimLib 0.0.05");

你初始化它的方式意味着它会在函数退出时自行销毁,因为它是在函数中声明和初始化的。 使用 new 将保证它存在,直到你删除它,因为除非你的代码这样做,否则它会不受干扰地坐在堆上的某个地方。

只需确保在包含它的 class 的析构函数中调用 delete m_window,以便在使用 new 创建时正确清理 window它。您还可以将 m_window 声明为 graphics::Screen 而不是 graphics::Screen* 并且只需将 m_window 分配为:

m_window = graphics::Screen(800,600,"ClimLib 0.0.05");

这样您就不必担心以后自己删除它,因为当包含 class 被删除时它会自行删除。