为什么最后一个窗口关闭时SDL不发出SDL_QUIT

时间:2019-05-15 23:10:20

标签: c++ sdl

我只是为了练习而编写游戏引擎,但我仍然坚持使用第一种语言。窗口管理器。

https://github.com/thebenius/SDL

我已经创建了一个GitHub Repo来向您显示代码,但是请不要担心。不多。但是我绝对不知道我的错误在哪里。

在代码中,我创建了三个窗口,并管理了SDL_QUIT的输入以停止游戏循环,并管理SDL_WINDOWEVENT_CLOSE的输入以关闭窗口。 一切正常,直到最后一个窗口关闭。据我所知,现在SDL_QUIT事件必须由SDL发出。但是Gameloop还在继续。

我认为我可能发生了某种内存泄漏,并且仍然保存了一个窗口。但是我检查了窗口堆栈(Window :: windows hashmap)是否为空。并清除main中的变量。

我还试图在哈希图中另外清除窗口和渲染器变量

Window ::〜Window(){

// Delete Window and Renderer
SDL_DestroyRenderer(Window::windows[this->windowID]->renderer);
SDL_DestroyWindow(Window::windows[this->windowID]->window);

Window::windows[this->windowID]->renderer = nullptr;
Window::windows[this->windowID]->window = nullptr;

// Delete Window from map
Window::windows.erase(this->windowID);

// Delete Window and Renderer
SDL_DestroyRenderer(this->renderer);
SDL_DestroyWindow(this->window);

// Reset Pointer
this->renderer = nullptr;
this->window = nullptr;

什么都没有。

我是C ++和SDL的新手。我希望你能帮助我。

2 个答案:

答案 0 :(得分:1)

谢谢o11c,

您的答案是谜语解决方案。 我只是将SDL_Quit()从析构函数中删除。显然,这阻止了事件处理程序捕获SDL_QUIT。所以我把它放在atexit()的构造函数中

之后(不知道为什么不这样做),我在删除main中的窗口指针时遇到了段错误。我删除了它,只是将它们全部设置为nullptr。

现在,WindowManager可以正常工作。谢谢您的帮助

答案 1 :(得分:0)

我认为SDL_QUIT只是一个钩子,如果您调用SDL_Quit(),则会为用户提供做一些退出工作的机会,

  

即使您已经使用SDL_QuitSubSystem()关闭了每个初始化的子系统,也应该调用此函数。即使在初始化错误的情况下,也可以安全地调用此函数

     

您可以将此功能与atexit()一起使用,以确保在关闭应用程序时运行该功能,但是从库或其他动态加载的代码中执行此操作是不明智的

要捕获窗口关闭事件,请参见SDL_WindowEventSDL_WINDOWEVENTSDL_WINDOWEVENT_CLOSE,关闭窗口的ID作为参数给出。

 *  \file SDL_quit.h
 *
 *  An ::SDL_QUIT event is generated when the user tries to close the application
 *  window.  If it is ignored or filtered out, the window will remain open.
 *  If it is not ignored or filtered, it is queued normally and the window
 *  is allowed to close.  When the window is closed, screen updates will
 *  complete, but have no effect.
 *
 *  SDL_Init() installs signal handlers for SIGINT (keyboard interrupt)
 *  and SIGTERM (system termination request), if handlers do not already
 *  exist, that generate ::SDL_QUIT events as well.  There is no way
 *  to determine the cause of an ::SDL_QUIT event, but setting a signal
 *  handler in your application will override the default generation of
 *  quit events for that signal.
 *
 *  \sa SDL_Quit()

SDL_EventType#SDL_QUIT

  

当用户单击最后一个现有窗口的关闭按钮时,将生成SDL_QUIT事件。

您不应在析构函数中调用SDL_Quit(),而只能在离开应用程序之前调用一次(建议与atexit()一起使用)

--- a/main.cpp
+++ b/main.cpp
@@ -32,17 +32,18 @@ int main() {

     }

-
     // Delete Windows
-    delete window;
-    delete window2;
-    delete window3;
+    // delete window;
+    // delete window2;
+    // delete window3;

     // reset pointer
     window = nullptr;
     window2 = nullptr;
     window3 = nullptr;

+    SDL_Quit();
+
     // Close Program properly
     return 0;  
 }
--- a/video/window.cpp
+++ b/video/window.cpp
@@ -51,7 +51,7 @@ Window::~Window() {
     // Shutdown if last window closed
     if(this->windows.empty()) {
         // Shutdown Video System
-        SDL_Quit();
+        // SDL_Quit();
         std::cout << "shuted down Video" << std::endl;
     }
 }