我的SDL程序在MinGW上运行时不返回(如下图)。如果我移动 SDL_Quit
在单人类的dtor之外到main的结尾,它不再有问题。所以我认为是构造销毁顺序的问题。但是没有其他需要破坏的东西。我到底做错了什么?
#include <SDL.h>
class ExceptionType {};
class SDL_DisplayType
{
public:
static SDL_DisplayType& Instance ()
{
static SDL_DisplayType myInstance;
return myInstance;
}
SDL_Window* sdlWindow_;
SDL_Renderer* sdlRenderer_;
private:
SDL_DisplayType ();
~SDL_DisplayType ();
};
SDL_DisplayType::SDL_DisplayType()
{
if (SDL_Init (SDL_INIT_EVERYTHING) < 0) throw ExceptionType ();
sdlWindow_ = SDL_CreateWindow ("",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,640, 480, 0);
if (! sdlWindow_) throw ExceptionType ();
sdlRenderer_ = SDL_CreateRenderer (sdlWindow_, -1, 0);
if (! sdlRenderer_) throw ExceptionType ();
}
SDL_DisplayType::~SDL_DisplayType ()
{
SDL_Quit (); //<-- Move this to end of main and problem goes away
}
int main (int argc, char** argv)
{
//draw something, just so I can call SDL_DisplayType::Instance
SDL_SetRenderDrawColor(SDL_DisplayType::Instance ().sdlRenderer_, 255, 255, 255, 255);
SDL_RenderDrawLine (SDL_DisplayType::Instance ().sdlRenderer_, 0, 0, 100, 100);
SDL_RenderPresent (SDL_DisplayType::Instance ().sdlRenderer_);
while (true) //wait for key hit
{
SDL_Event sdlEvent;
if (SDL_WaitEvent (&sdlEvent) == 0) throw ExceptionType ();
if (sdlEvent.type == SDL_KEYDOWN) break ;
}
return 0;
}
Makefile,如果有用的话。
INCLUDE_FLAGS = -I..\..\SDL2-MinGW\SDL2\i686-w64-mingw32\include\SDL2 \
-I..\..\SDL2-MinGW\SDL2_image\i686-w64-mingw32\include\SDL2 \
-I..\..\SDL2-MinGW\SDL2_mixer\i686-w64-mingw32\include\SDL2 \
-I..\..\SDL2-MinGW\SDL2_ttf\i686-w64-mingw32\include\SDL2
LIBRARY_PATH = -L..\..\SDL2-MinGW\SDL2\i686-w64-mingw32\lib \
-L..\..\SDL2-MinGW\SDL2_image\i686-w64-mingw32\lib \
-L..\..\SDL2-MinGW\SDL2_mixer\i686-w64-mingw32\lib \
-L..\..\SDL2-MinGW\SDL2_ttf\i686-w64-mingw32\lib
a.out: main.o
g++ -g $(LIBRARY_PATH) main.o -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -L.
main.o: main.cpp
g++ -g -c $(INCLUDE_FLAGS) main.cpp
在C++中,对静态数据的销毁顺序没有约束(当编译在分离的文件中时)。那么,千万不要在一个单子的destructor中使用(直接或不使用)静态数据,因为你无法知道数据是否还存在。
在你的情况下,你可能尝试调用一些已经被销毁的SDL东西。
但是没有其他需要被销毁的东西。我到底做错了什么?
那么,通过查看你的 SDL_DisplayType
's 破坏者:
SDL_DisplayType::~SDL_DisplayType ()
{
SDL_Quit ();
}
你可以意识到,这两个 SDL_DisplayType
的数据成员 - sdlWindow_
和 sdlRenderer_
- 创立于 构造者但它们在这里并没有被销毁,而是在相应的destructor中。
请考虑在相应的分解器中调用 SDL_DestroyRenderer()
和 SDL_DestroyWindow()
- 按照这个顺序 SDL_DisplayType
的析构器,然后再调用 SDL_Quit()
即:
SDL_DisplayType::~SDL_DisplayType () {
SDL_DestroyRenderer(sdlRenderer_);
SDL_DestroyWindow(sdlWindow_);
SDL_Quit ();
}