为什么 SDL 在最后 windows 关闭时不发出 SDL_QUIT

Why does SDL doesn't emit SDL_QUIT when last windows closed

我正在编写一个游戏引擎只是为了练习,但我仍然坚持第一个挑战。 Window 经理。

https://github.com/thebenius/SDL

我已经创建了一个 GitHub 存储库来向您展示代码,但请不要担心。它并不多。但是我完全不知道我的错误在哪里。

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

我想我可能有一种内存泄漏,但仍然有 windows 保存。但是我检查了 window 堆栈 (Window::windows hashmap) 它是空的。并且main中的变量也被清除了。

我还尝试另外清除散列映射中的 window 和渲染器变量

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 的新手。希望你能帮帮我。

我认为 SDL_QUIT 只是一个挂钩,如果你调用 SDL_Quit(),给用户机会做一些 quit stuff,手册:

You should call this function even if you have already shutdown each initialized subsystem with SDL_QuitSubSystem(). It is safe to call this function even in the case of errors in initialization

You can use this function with atexit() to ensure that it is run when your application is shutdown, but it is not wise to do this from a library or other dynamically loaded code

要捕获 window 关闭事件,请参阅 SDL_WindowEventSDL_WINDOWEVENTSDL_WINDOWEVENT_CLOSE,关闭 window 的 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

An SDL_QUIT event is generated when the user clicks on the close button of the last existing window.

你不应该在析构函数中调用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;
     }
 }

谢谢o11c,

你的答案是谜语。 我只是把 SDL_Quit() 从析构函数中取出来。这显然阻止了事件处理程序捕获 SDL_QUIT。所以我把它放到 atexit()

的构造函数中

在那之后(不知道为什么之前没有)我在删除 main 中的 window 指针时遇到了段错误。我删除了它,然后将它们全部设置为 nullptr。

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