| Summary: | Crash when quitting application with fullscreen window | ||
|---|---|---|---|
| Product: | SDL | Reporter: | mattreecebentley |
| Component: | *don't know* | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | ||
| Version: | 2.0.0 | ||
| Hardware: | x86 | ||
| OS: | Windows (XP) | ||
I haven't seen this before. Any chance you can get a stack trace to find out where it's crashing? For that code I can't get a stack trace to come up, but for the OO code which displays the same error, I get the following under codelite:
0 0x4fdf6040 ??
1 0x7e418734 USER32!GetDC
2 0x000103f8 ??
3 0x7e418816 USER32!GetDC
4 0x4fdf6040 ??
5 0x000103f8 ??
6 0x7e428ea0 USER32!DefWindowProcW
7 0x00000000 ??
However running it a second time gives me:
0 0x4fdf6040 ??
1 0x7e418734 USER32!GetDC
2 0x0006014e ??
3 0x0000007e ??
4 0x00000020 ??
5 0x04000500 ??
6 0x4fdf6040 ??
7 0xdcbaabcd ??
8 0x00000000 ??
Seems a bit random.
With the non-OO code above, sometimes I get a crash, sometimes I get a complete but a return code of -1073741819, depending on whether I clean and build etc.
The OO code if you need it - just a library/wrapper I'm working on:
//Using SDL and standard IO
#include "SDL.h"
#include "SDL_image.h"
#include <iostream>
#include <fstream>
#include <ctime>
class platforma_log
{
private:
std::ofstream logfile;
time_t logtime;
struct tm *logtimestruct;
public:
platforma_log();
platforma_log(const char *logfile_name, bool append);
~platforma_log();
void write_time();
bool is_initialised();
template <typename logtemplate>
friend platforma_log& operator << (platforma_log& log, const logtemplate& value);
friend platforma_log& operator << (platforma_log& log, std::ostream& (*pf) (std::ostream&));
};
platforma_log::platforma_log()
{
logfile.open("platforma_log.txt");
if (!logfile.is_open())
{
std::cerr << "Platforma_log Constructor: Problem! Logfile 'platforma_log.txt' could not be created. Check path/locking." << std::endl;
}
}
platforma_log::platforma_log(const char *logfile_name, bool append)
{
if (append)
{
logfile.open(logfile_name, std::ofstream::out | std::ofstream::app);
}
else
{
logfile.open(logfile_name);
}
if (!logfile.is_open())
{
std::cerr << "Platforma_log Constructor: Problem! Logfile '" << logfile_name << "' could not be opened. Check filename/path/locking." << std::endl;
}
}
platforma_log::~platforma_log()
{
logfile.close();
}
void platforma_log::write_time()
{
logtime = time(0);
logtimestruct = localtime(& logtime);
if (logfile.is_open())
{
logfile << (logtimestruct->tm_year + 1900) << '-' << (logtimestruct->tm_mon + 1) << '-' << logtimestruct->tm_mday << ", " << logtimestruct->tm_hour << ":" << logtimestruct->tm_min << " : " << std::endl;
}
}
template <typename logtemplate>
platforma_log& operator << (platforma_log& log, logtemplate const & value)
{
if (log.logfile.is_open())
{
log.logfile << value;
log.logfile.flush();
}
return log;
}
platforma_log& operator << (platforma_log& log, std::ostream& (*pf) (std::ostream&))
{
if (log.logfile.is_open())
{
log.logfile << pf;
log.logfile.flush();
}
return log;
}
bool platforma_log::is_initialised()
{
if (logfile.is_open())
{
return true;
}
else
{
return false;
}
}
class platforma_window
{
private:
SDL_Window* p_window;
SDL_Surface* p_window_surface;
public:
platforma_window(const char *window_title, unsigned int window_width, unsigned int window_height, bool fullscreen, platforma_log *log);
~platforma_window();
SDL_Window* get();
SDL_Surface* get_surface();
bool is_initialised();
};
platforma_window::platforma_window(const char *window_title, unsigned int window_width, unsigned int window_height, bool fullscreen, platforma_log *log)
{
p_window = NULL;
p_window_surface = NULL;
if (log == NULL)
{
std::cerr << "Platforma_window constructor: Error: log is NULL. Quitting." << std::endl;
return;
}
// Create a window, fallback to non-opengl if opengl not available, fallback to windowed if fullscreen specified but not available:
Uint32 default_window_flags = SDL_WINDOW_SHOWN|SDL_WINDOW_INPUT_FOCUS;
if (window_width != 0 && window_height != 0)
{
if (fullscreen)
{
//Create window with opengl possible
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags|SDL_WINDOW_OPENGL|SDL_WINDOW_FULLSCREEN);
if (p_window == NULL)
{
*log << "Platforma_window constructor: Window could not be created with opengl, trying without opengl. SDL_Error: " << SDL_GetError() << std::endl;
// Try without opengl
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags|SDL_WINDOW_FULLSCREEN);
if (p_window == NULL)
{
*log << "Platforma_window constructor: Window could not be created without opengl and fullscreen, trying without fullscreen. SDL_Error: " << SDL_GetError() << std::endl;
// Try without opengl and fullscreen
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags);
}
}
}
else // no fullscreen
{
//Create window with opengl enabled
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags|SDL_WINDOW_OPENGL);
if (p_window == NULL)
{
*log << "Platforma_window constructor: Non-fullscreen window could not be created with opengl, trying without opengl. SDL_Error: " << SDL_GetError() << std::endl;
// Try without opengl
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags);
}
}
}
else // Assume fullscreen desktop mode (window height and width == 0).
{
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags|SDL_WINDOW_OPENGL|SDL_WINDOW_FULLSCREEN_DESKTOP|SDL_WINDOW_BORDERLESS);
if (p_window == NULL)
{
*log << "Platforma_window constructor: Fullscreen desktop window could not be created with opengl, trying without opengl. SDL_Error: " << SDL_GetError() << std::endl;
// Try without opengl
p_window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, default_window_flags|SDL_WINDOW_FULLSCREEN_DESKTOP|SDL_WINDOW_BORDERLESS);
}
}
if (p_window == NULL)
{
*log << "Platforma_window constructor: Error! Window could not be created! SDL_Error:" << SDL_GetError();
}
else
{
//Get window surface
p_window_surface = SDL_GetWindowSurface(p_window);
}
}
platforma_window::~platforma_window()
{
SDL_DestroyWindow(p_window);
p_window = NULL;
p_window_surface = NULL;
}
SDL_Window* platforma_window::get()
{
return p_window;
}
SDL_Surface* platforma_window::get_surface()
{
return p_window_surface;
}
bool platforma_window::is_initialised()
{
return (p_window != NULL);
}
class platforma_renderer
{
private:
SDL_Renderer* p_renderer;
public:
platforma_renderer(SDL_Window *window, unsigned int logical_width, unsigned int logical_height, platforma_log *p_log);
~platforma_renderer();
SDL_Renderer* get();
bool is_initialised();
};
platforma_renderer::platforma_renderer(SDL_Window *window, unsigned int logical_width, unsigned int logical_height, platforma_log *log)
{
p_renderer = NULL;
if (log == NULL)
{
std::cerr << "Platforma_renderer constructor: Error: log is NULL. Quitting." << std::endl;
return;
}
// Try for hardware acceleration, vsync, rendering to textures, fallback to software rendering without vsync if unavailable:
p_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC|SDL_RENDERER_TARGETTEXTURE);
if (p_renderer == NULL)
{
*log << "Platforma_renderer constructor: Renderer could not be created, trying without texture rendering. SDL_Error:" << SDL_GetError() << std::endl;
p_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
if (p_renderer == NULL)
{
*log << "Platforma_renderer constructor: Renderer could not be created, trying without VSYNC. SDL_Error:" << SDL_GetError() << std::endl;
p_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (p_renderer == NULL)
{
*log << "Platforma_renderer constructor: Renderer could not be created, trying software with VSYNC. SDL_Error:" << SDL_GetError() << std::endl;
p_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE|SDL_RENDERER_PRESENTVSYNC);
if (p_renderer == NULL)
{
*log << "Platforma_renderer constructor: Renderer could not be created, trying software without VSYNC. SDL_Error:" << SDL_GetError() << std::endl;
p_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
if (p_renderer == NULL)
{
*log << "Platforma_renderer constructor: Renderer could not be created! SDL_Error:" << SDL_GetError() << std::endl;
}
}
}
}
}
if (p_renderer != NULL)
{
SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "linear");
SDL_RenderSetLogicalSize(p_renderer, logical_width, logical_height);
SDL_RenderClear(p_renderer);
}
}
platforma_renderer::~platforma_renderer()
{
// Destroy renderer
SDL_DestroyRenderer(p_renderer);
p_renderer = NULL;
}
SDL_Renderer* platforma_renderer::get()
{
return p_renderer;
}
bool platforma_renderer::is_initialised()
{
return (p_renderer != NULL);
}
class platforma_texture
{
private:
SDL_Texture *p_texture;
SDL_Renderer *p_renderer;
int width, height;
Uint32 format;
public:
platforma_texture(SDL_Renderer *renderer, const char *image_filename, platforma_log *log);
~platforma_texture();
SDL_Texture * get();
void get_dimensions(int &texture_width, int &texture_height);
void get_format(Uint32 &format);
bool is_initialised();
// int copy(int x, int y, unsigned int width, unsigned width height)
};
platforma_texture::platforma_texture(SDL_Renderer *renderer, const char *image_filename, platforma_log *log)
{
p_texture = NULL;
width = 0;
height = 0;
format = 0;
p_renderer = renderer;
if (log == NULL)
{
std::cerr << "Platforma_texture constructor: Error: log is NULL. Quitting." << std::endl;
return;
}
if (renderer == NULL)
{
*log << "Platforma_texture constructor: Error: renderer is NULL. Quitting." << std::endl;
return;
}
p_texture = IMG_LoadTexture(p_renderer, image_filename);
if(p_texture == NULL)
{
*log << "Platforma_texture constructor: Unable to load image file to texture! SDL Error: " << SDL_GetError() << std::endl;
}
else
{
SDL_QueryTexture(p_texture, &format, NULL, &width, &height);
}
}
platforma_texture::~platforma_texture()
{
if (p_texture != NULL)
{
SDL_DestroyTexture(p_texture);
p_texture = NULL;
}
}
SDL_Texture* platforma_texture::get()
{
return p_texture;
}
void platforma_texture::get_dimensions(int &texture_width, int &texture_height)
{
texture_width = width;
texture_height = height;
}
void platforma_texture::get_format(Uint32 &texture_format)
{
texture_format = format;
}
bool platforma_texture::is_initialised()
{
return (p_texture != NULL);
}
class platforma
{
private:
platforma_log *log;
platforma_window *window;
platforma_renderer *renderer;
//platforma_sprites *sprites;
bool initialised;
public:
platforma(const char *window_name, unsigned int window_width, unsigned int window_height, unsigned int renderer_width, unsigned int renderer_height, bool fullscreen);
~platforma();
SDL_Window* get_window();
SDL_Renderer* get_renderer();
platforma_log* get_log();
bool is_initialised();
};
platforma::platforma(const char *window_name, unsigned int window_width, unsigned int window_height, unsigned int renderer_width, unsigned int renderer_height, bool fullscreen)
{
initialised = false;
log = NULL;
window = NULL;
renderer = NULL;
// Log already initialised, check if initialised correctly:
log = new platforma_log;
if (!log->is_initialised())
{
std::cerr << "Platforma Constructor: Log could not initialize! Quitting." << std::endl;
return;
}
*log << "Platforma initialising. Date/time ";
log->write_time();
// Initialise SDL:
if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_EVENTS|SDL_INIT_TIMER) < 0 )
{
*log << "Platforma Constructor: SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return;
}
*log << "SDL video, audio, timer and events initialised." << std::endl;
// Initialise SDL_IMG for use with PNGs only:
if(IMG_Init(IMG_INIT_PNG) == 0)
{
*log << "Platforma Constructor: SDL_img PNG support could not initialize! Quitting." << std::endl;
return;
}
*log << "SDL_img initialised with PNG support." << std::endl;
// Initialise Window:
window = new platforma_window(window_name, window_width, window_height, fullscreen, log);
if (!window->is_initialised())
{
*log << "Platforma Constructor: Window could not initialize! SDL_Error: " << SDL_GetError() << ". Quitting." << std::endl;
delete window;
delete log;
return;
}
*log << "SDL Window " << window_name << " created with dimensions" << window_width << "*" << window_height << "." << std::endl;
// Initialise Renderer:
renderer = new platforma_renderer(window->get(), renderer_width, renderer_height, log);
if (!renderer->is_initialised())
{
*log << "Platforma Constructor: Renderer could not initialize! SDL_Error: " << SDL_GetError() << ". Quitting." << std::endl;
delete renderer;
delete window;
delete log;
return;
}
*log << "SDL Renderer created with logical dimensions" << renderer_width << "*" << renderer_height << "." << std::endl;
// Initialise Sprites:
// Platforma is correctly initialised:
initialised = true;
}
platforma::~platforma()
{
// Destroy Sprites:
// Destroy Renderer:
if (renderer != NULL)
{
delete renderer;
}
// Destroy Window:
if (window != NULL)
{
delete window;
}
// Close log:
if (log != NULL)
{
delete log;
}
// Destroy SDL:
SDL_Quit();
}
SDL_Renderer* platforma::get_renderer()
{
return renderer->get();
}
SDL_Window* platforma::get_window()
{
return window->get();
}
platforma_log* platforma::get_log()
{
return log;
}
bool platforma::is_initialised()
{
return initialised;
}
int main( int argc, char* args[] )
{
platforma *engine;
engine = new platforma ("Platforma test", 640, 480, 600, 400, true);
if (!engine->is_initialised())
{
return -1;
}
platforma_texture *thetexture1, *thetexture2;
thetexture1 = new platforma_texture(engine->get_renderer(), "image2.png", engine->get_log());
thetexture2 = new platforma_texture(engine->get_renderer(), "image.png", engine->get_log());
//Load media
if(!thetexture1->is_initialised() || !thetexture2->is_initialised())
{
std::cerr << "Failed to load media!" << std::endl;
return -1;
}
//Apply the image
SDL_RenderCopy(engine->get_renderer(), thetexture2->get(), NULL, NULL);
//Apply the image
SDL_RenderCopy(engine->get_renderer(), thetexture1->get(), NULL, NULL);
//Update the surface
SDL_RenderPresent(engine->get_renderer());
//Wait two seconds
SDL_Delay( 2000 );
delete thetexture2;
delete thetexture1;
delete engine;
//Quit SDL subsystems
SDL_Quit();
return 0;
}
Just tried with 2.01, same issue. Still crashes on true fullscreen, 100% fine on windowed or fullscreen desktop. Correction - this IS fixed in 2.01, I forgot to replace the sdl dll in the project directory. |
The same code works fine when using non-fullscreen modes, or when using desktop fullscreen. Unfortunately on multiple machines (one, eeepc with intel graphics chipset, two, desktop with ati 5800) and under XP, using mingw, SDL2 crashes when exiting fullscreen mode. There's no problems with the code AFAIK, and neither of the machines have problems with (non-desktop) fullscreen games. The code below is just some simple instantiation for demonstration purposes, no texture displays etc. In my real OO code with textures displayed, it does exactly the same thing. Changing the resolution size makes no difference. The problem may be specific to mingw + SDL2, or it may be specific to XP + SDL2. Or a combination. Using Codelite 5.2 IDE with mingw TDM-GCC 4.71 (x86). //Using SDL, SDL_image, standard IO, and strings #include "SDL.h" #include <stdio.h> #include <string> //Screen dimension constants const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; //Starts up SDL and creates window bool init(); //Frees media and shuts down SDL void close(); //The window we'll be rendering to SDL_Window* gWindow = NULL; //The window renderer SDL_Renderer* gRenderer = NULL; bool init() { //Initialization flag bool success = true; //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() ); success = false; } else { //Set texture filtering to linear if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) ) { printf( "Warning: Linear texture filtering not enabled!" ); } //Create window gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN|SDL_WINDOW_FULLSCREEN ); if( gWindow == NULL ) { printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() ); success = false; } else { //Create renderer for window gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED ); if( gRenderer == NULL ) { printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() ); success = false; } else { //Initialize renderer color SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF ); } } } return success; } void close() { //Destroy window SDL_DestroyRenderer( gRenderer ); SDL_DestroyWindow( gWindow ); gWindow = NULL; gRenderer = NULL; //Quit SDL subsystems SDL_Quit(); } int main( int argc, char* args[] ) { //Start up SDL and create window if( !init() ) { printf( "Failed to initialize!\n" ); } else { SDL_Delay(2000); } //Free resources and close SDL close(); return 0; }