We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2159 - Crash when quitting application with fullscreen window
Summary: Crash when quitting application with fullscreen window
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: *don't know* (show other bugs)
Version: 2.0.0
Hardware: x86 Windows (XP)
: P2 major
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-10-18 08:04 UTC by mattreecebentley
Modified: 2013-10-25 10:26 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mattreecebentley 2013-10-18 08:04:13 UTC
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;
}
Comment 1 Sam Lantinga 2013-10-21 04:40:03 UTC
I haven't seen this before.  Any chance you can get a stack trace to find out where it's crashing?
Comment 2 mattreecebentley 2013-10-22 05:19:13 UTC
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;
}
Comment 3 mattreecebentley 2013-10-25 09:28:41 UTC
Just tried with 2.01, same issue. Still crashes on true fullscreen, 100% fine on windowed or fullscreen desktop.
Comment 4 mattreecebentley 2013-10-25 10:26:18 UTC
Correction - this IS fixed in 2.01, I forgot to replace the sdl dll in the project directory.