SDL_GetRendererInfo crash - c++

the following program runs until SDL_GetRendererInfo is called (in function RenderInit()), and then stops working before SDL_GetError can do anything. replacing global_renderer with a null SDL_Renderer pointer doesn't cause a crash and the expected sdl error is gotten.
#include <iostream>
#include <list>
#include "SDL.h"
using namespace std;
//global variables:
bool run = true; // whether or not the program should be running
int global_window_width = 50; //width of window in tiles
int global_window_height = 35; //height of window in tiles
SDL_Window* global_window = NULL; //points to primary window
SDL_Renderer* global_renderer = NULL; //points to renderer for main window
SDL_RendererInfo* global_renderer_info = NULL; //points to info about above renderer once it's initialized
SDL_Texture* spritesheet = NULL; //holds the spritesheet
SDL_Event event; //for holding currently in-handling event
//function declarations:
int init(); //initialize SDL
int windowInit(); //initialize window
int renderInit(); //create renderers
int viewInit(); //manages all window, rendering, etc stuff
int loadSpritesheet(); //loads spritesheet
void cleanup(); //free up memory, etc
void dispatchEvent(); //main event handling
//function definitions:
int init()
{
if ( SDL_Init(SDL_INIT_EVERYTHING) !=0 )
{
cout << "could not initialize SDL. " << SDL_GetError();
return 1;
}
return 0;
}
int windowInit()
{
global_window = SDL_CreateWindow("roguelike",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
global_window_width * 10,
global_window_height * 10,
SDL_WINDOW_SHOWN);
if(global_window == NULL)
{
cout << "could create window. " << SDL_GetError();
return 1;
}
return 0;
}
int renderInit()
{
global_renderer = SDL_CreateRenderer(global_window,
-1,
SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED );
if (global_renderer == NULL)
{
cout << "could not create renderer" << SDL_GetError();
return 1;
}
SDL_SetRenderDrawColor(global_renderer,0xFF,0xFF,0xFF,0xFF);
if (SDL_GetRendererInfo(global_renderer, global_renderer_info) != 0)
{
cout << "could not get renderer info" << SDL_GetError();
return 1;
}
return 0;
}
int viewInit()
{
if (windowInit() == 1)
{
return 1;
}
else if(renderInit() == 1)
{
return 1;
}
else if(loadSpritesheet() == 1)
{
return 1;
}
return 0;
}
int loadSpritesheet()
{
SDL_Surface* tempsurf = NULL; //using surface to get image initially, but since surfaces use cpu rendering we switch to textures immediately
tempsurf = SDL_LoadBMP("spritesheet.bmp"); //puts image in the surface
if (tempsurf == NULL)
{
cout << "failed to load spritesheet";
SDL_FreeSurface(tempsurf); //we don't need tempsurf anymore
return 1;
}
spritesheet = SDL_CreateTextureFromSurface(global_renderer, tempsurf);
if (spritesheet == NULL)
{
cout << "failed to create spritesheet texture";
SDL_FreeSurface(tempsurf); //we don't need tempsurf anymore
return 1;
}
SDL_FreeSurface(tempsurf); //we don't need tempsurf anymore
return 0;
}
void cleanup()
{
SDL_DestroyWindow(global_window);
global_window = NULL;
SDL_DestroyRenderer(global_renderer);
global_renderer = NULL;
SDL_DestroyTexture(spritesheet);
spritesheet = NULL;
global_renderer_info = NULL;
SDL_Quit();
}
void dispatchEvent()
{
SDL_PollEvent(&event); //stores current event information
switch(event.type)
{
case SDL_QUIT:
{
run = false;
break;
}
}
}
//classes:
class Layer // each layer holds visuals for a certain subset of what is to be displayed; environment, HUD, menu, etc.
{
Layer(){};
};
class Camera //renders environment, ui, etc in a series of layers
{
int width, height; //in tiles
SDL_Texture* texture_draw; //texture the camera draws to and sends to be displayed
list<Layer*> layer_list; //list of layers to be rendered, back --> front
public:
Camera(int x, int y, SDL_Renderer* renderer): width(x), height(y) //(width, height, renderer for camera to use)
{
texture_draw = SDL_CreateTexture(global_renderer,global_renderer_info->texture_formats[0] , SDL_TEXTUREACCESS_TARGET, 10*width, 10*height);
};
};
//main loop
int main(int argc, char *argv[]) //main function, needed by SDL
{
if(init() == 0)
{
if(viewInit() == 0)
{
while(run)
{
dispatchEvent();
}
}
}
cleanup();
return 0;
}

You're asking SDL_GetRendererInfo to write renderer info to location global_renderer_info points to, which is NULL. Writing to NULL causes segmentation fault. This should be expected behaviour.
Correct code should allocate memory for renderer info (preferably on stack or in global area) and write to that location, e.g.:
SDL_RendererInfo info = {0};
SDL_GetRendererInfo(global_renderer, &info);
// ... use info fields

Fixed by: instead of declaring global_renderer_info as a pointer to an SDL_RendererInfo, I instead declared the object directly and changed the rest of the code accordingly.

Related

"Class" type redefinition error C2011 in C++

Here's my header file:
#ifndef SOMETHING_H
#define SOMETHING_H
#include <SDL.h>
#include <stdio.h>
#include <string>
#pragma once
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS;
int SCREEN_HEIGHTS;
//Starts up SDL and creates window
bool inits();
//Loads media
bool loadMediases();
//Frees media and shuts down SDL
void closes();
Something(int height);
int mains();
//Loads individual image
SDL_Surface* loadSurfaces(std::string path);
//The window we'll be rendering to
SDL_Window* gWindows;
//The surface contained by the window
SDL_Surface* gScreenSurfaces;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[5];
//Current displayed image
SDL_Surface* gCurrentSurfaces;
};
#endif
Here's my cpp file:
//Using SDL, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string>
#include "Something.h"
class Something {
public:
//Screen dimension constants
int SCREEN_WIDTHS = 640;
int SCREEN_HEIGHTS = 480;
//Key press surfaces constants
enum KeyPressSurfaceses
{
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_TOTAL
};
//The window we'll be rendering to
SDL_Window* gWindows = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurfaces = NULL;
//The images that correspond to a keypress
SDL_Surface* gKeyPressSurfaceses[KEY_PRESS_SURFACE_TOTAL];
//Current displayed image
SDL_Surface* gCurrentSurfaces = NULL;
Something(int height) {
SCREEN_HEIGHTS = height;
}
bool inits()
{
//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
{
//Create window
gWindows = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTHS, SCREEN_HEIGHTS, SDL_WINDOW_SHOWN);
if (gWindows == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Get window surface
gScreenSurfaces = SDL_GetWindowSurface(gWindows);
}
}
return success;
}
bool loadMedias()
{
//Loading success flag
bool success = true;
//Load default surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] = loadSurfaces("resources/images/press.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT] == NULL)
{
printf("Failed to load default image!\n");
success = false;
}
//Load up surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] = loadSurfaces("resources/images/up.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP] == NULL)
{
printf("Failed to load up image!\n");
success = false;
}
//Load down surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] = loadSurfaces("resources/images/down.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN] == NULL)
{
printf("Failed to load down image!\n");
success = false;
}
//Load left surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] = loadSurfaces("resources/images/left.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT] == NULL)
{
printf("Failed to load left image!\n");
success = false;
}
//Load right surface
gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] = loadSurfaces("resources/images/right.bmp");
if (gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT] == NULL)
{
printf("Failed to load right image!\n");
success = false;
}
return success;
}
void closes()
{
//Deallocate surfaces
for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; ++i)
{
SDL_FreeSurface(gKeyPressSurfaceses[i]);
gKeyPressSurfaceses[i] = NULL;
}
//Destroy window
SDL_DestroyWindow(gWindows);
gWindows = NULL;
//Quit SDL subsystems
SDL_Quit();
}
SDL_Surface* loadSurfaces(std::string path)
{
//Load image at specified path
SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
if (loadedSurface == NULL)
{
printf("Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
return loadedSurface;
}
int mains(int argc, char* args[])
{
//Start up SDL and create window
if (!inits())
{
printf("Failed to initialize!\n");
}
else
{
//Load media
if (!loadMedias())
{
printf("Failed to load media!\n");
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Set default current surface
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT];
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//User presses a key
else if (e.type == SDL_KEYDOWN)
{
//Select surfaces based on key press
switch (e.key.keysym.sym)
{
case SDLK_UP:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_RIGHT];
break;
default:
gCurrentSurfaces = gKeyPressSurfaceses[KEY_PRESS_SURFACE_DEFAULT];
break;
}
}
}
//Apply the current image
SDL_BlitSurface(gCurrentSurfaces, NULL, gScreenSurfaces, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindows);
}
}
}
//Free resources and close SDL
closes();
return 0;
}
};
Why does it keep throwing a "Class" type redefinition error? How can I fix this? I've tried everything but I just run into more problems. I saw some posts relating the issue to defining the class twice, but getting rid of the class definition in the cpp and using classname::functionname just causes more errors.
I know this is a stupid problem to have, I'm a beginning C++ programmer using tutorials and Visual Studio.
In your .cpp file you have completely redeclared class Something. That's not how you do it if you want to just put the implementations of functions in the .cpp file.
The syntax in there should be like:
bool Something::inits()
{
// implementation ...
}
bool Something::loadMedias()
{
// implementation ...
}
And so on

SDL_Log outputting ??" when trying to output a string

I've been trying to send a log in the console to make sure the player was created, but here is the results:
Here is the code along the problematic part:
SDL_Log("%s has %i hp out of %i", player1.name, player1.health, player1.maxhealth);
systemValues.h:
// Core Libraries and Headers
// - Global includes
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
#include <typeinfo>
// Defines
#define GRAPHICS "../resources/"
struct Player
{
std::string sprite;
std::string name;
int level;
int size;
int health;
int maxhealth;
int magicpower; // Magic Points
int damages;
int armor;
int magic;
};
struct Enemy
{
std::string sprite;
std::string name;
int level;
int size;
int health;
int maxhealth;
int magicpower; // Magic Points
int damages;
int armor;
int magic;
};
Player createPlayer(std::string name);
Enemy createEnemy(std::string name, int level);
int damagePlayer(Player target, int damages);
int damageEnemy(Enemy target, int damages);
void close();
main.cpp:
// Local includes
// - Custom Headers
#include "systemValues.h"
// Screen constants and dimensions. (TODO: MOVE TO A PROPER HEADER FILE.)
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
// The window that is rendered to
SDL_Window* window = NULL;
// Quit being false means the application is running and did not request to quit
bool quit = false;
// Event handler
SDL_Event e;
// The surface contained by the window
SDL_Surface* screenSurface = NULL;
// Main function
int main(int argc, char* args[])
{
// Initializing SDL
if (SDL_Init(SDL_INIT_VIDEO)<0)
{
SDL_Log("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
// Creating the window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
{
SDL_Log("The window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
Player player1 = createPlayer("Avarthar");
Enemy enemy1 = createEnemy("Blob", 1);
// Get the window surface
screenSurface = SDL_GetWindowSurface(window);
// While the application is running
while (!quit){
while (SDL_PollEvent(&e) != 0)
{
// User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
// Checks for a key being pressed down
else if (e.type == SDL_KEYDOWN)
{
switch(e.key.keysym.sym)
{
// Checks if the key is F
case SDLK_f:
player1.health = damagePlayer(player1, 5);
SDL_Log("%s has %i hp out of %i", player1.name, player1.health, player1.maxhealth); // TODO - Remove the test line
break;
case SDLK_ESCAPE:
quit = true;
break;
}
}
}
// Test if player is created
if (player1.name == "Avarthar")
{
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, (player1.health*-1+100*2), player1.health*2, 0));
}
else
{
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 255, 255, 255));
}
// Update the surface
SDL_UpdateWindowSurface(window);
}
}
}
close();
// Return 0 to terminate the program
return 0;
}
// Creates a player with the given varables
Player createPlayer(std::string name)
{
Player player;
player.sprite = "";
player.name = name;
player.level = 1;
player.size = 32;
player.health = 100;
player.maxhealth = 100;
player.magicpower = 100;
player.damages = 1;
player.armor = 0;
player.magic = 1;
return player;
}
Enemy createEnemy(std::string name, int level)
{
Enemy enemy;
enemy.sprite = "";
enemy.name = name;
enemy.level = level;
enemy.size = 32;
enemy.health = 100;
enemy.maxhealth = 100;
enemy.magicpower = 100; // Magic Points
enemy.damages = 1;
enemy.armor = 0;
enemy.magic = 1;
return enemy;
}
// Deals damage to the target of type Player
int damagePlayer(Player target, int damages)
{
target.health -= damages;
// Checks whether the target is in the health range or not
if (target.health < 0)
target.health = 0;
if (target.health > target.maxhealth)
target.health = target.maxhealth;
return target.health;
}
// Deals damage to the target of type Enemy
int damageEnemy(Enemy target, int damages)
{
target.health -= damages;
// Checks whether the target is in the health range or not
if (target.health < 0)
target.health = 0;
if (target.health > target.maxhealth)
target.health = target.maxhealth;
return target.health;
}
void close()
{
// Wait 0.1 seconds
SDL_Delay(100);
// Clear the window from the memory
SDL_DestroyWindow(window);
// Quit the SDL subsystems
SDL_Quit();
}
What I tried so far:
I tried with &player1.name and it didn't change anything.
I also tried with only SDL_Log("%s", player1.name); and it instead wrote a single ? in the outputs.
The color changing according to the player1.health is working without any problem, but as soon as I try getting and sending the name in the SDL_Log it sends the outputs shown in the screenshot above.
SDL_Log cannot do std::string. Use player1.name.c_str(). This should have triggered a warning, check your compiler flags. – Quentin
Thanks for the quick answer and also thanks for noticing another problem that I had with my compiler ^^

SDL_UpperBlit: passed a NULL surface error

In the following code:
#include <iostream>
#include "SDL.h"
using namespace std;
int main(int argc, char** argv)
{
SDL_Surface* screenSurface = nullptr;
SDL_Surface* image = nullptr;
SDL_Window* window = nullptr;
const Uint8* keystate;
SDL_Rect offset;
offset.x = 100;
offset.y = 200;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
cout << "Window initialization error: " << SDL_GetError();
}
else
{
window = SDL_CreateWindow("game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
bool isRunning = true;
SDL_Event ev;
//game loop
while (isRunning)
{
while (SDL_PollEvent(&ev) != 0)
{
if (ev.type == SDL_QUIT)
isRunning = false;
}
keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
offset.y -= 1;
}
else if (keystate[SDL_SCANCODE_A])
{
offset.x -= 1;
}
else if (keystate[SDL_SCANCODE_S])
{
offset.y += 1;
}
else if (keystate[SDL_SCANCODE_D])
{
offset.x += 1;
}
screenSurface = SDL_GetWindowSurface(window);
image = SDL_LoadBMP("world.bmp");
SDL_BlitSurface(image, NULL, screenSurface, &offset);
SDL_UpdateWindowSurface(window);
cout << SDL_GetError() << endl;
}
}
SDL_FreeSurface(image);
SDL_DestroyWindow(window);
image = nullptr;
window = nullptr;
SDL_Quit();
return 0;
}
I get an error, saying: "SDL_UpperBlit: passed a NULL surface error." But the error did not occur until I went from using a switch statement in the while loop for SDL_PollEvent, to just using if statements using SDL_SCANCODE_ in the isRunning while loop. So the error does not occur instantly, but after a short while, like 10 seconds or so. So I am able to move around the world.bmp with WASD for a short while, then I get the error "SDL_UpperBlit: passed a NULL surface error.".
What's the solution for this?
image = SDL_LoadBMP("world.bmp");
This loads world.bmp from the disk, creates a brand new surface and stores the image inside. You never destroy this surface, and you don't check for errors either.
As you're running this once per frame, SDL quickly runs out of resources, SDL_LoadBMP returns NULL to signal it, and you pass that NULL to SDL_BlitSurface.
Only load your resources once, and take care of destroying them at the right time. C++ has smart pointers and RAII to do that for you.

Unhandled exception in font render function C++ SDL

I'm working on a PONG clone and just on the title screen. I have a class to work the title screen loop of the state machine and it uses very little, only a single sprite and a single true type font message. But when I call the function to render the message onto the SDL_Surface, it throws my program into whack. The error I receive is Unhandled exception at 0x6F4C2A9D (SDL_ttf.dll) in Pong.exe: 0xC0000005: Access violation reading location 0x00000000. Usually this means that I didn't initialize something or didn't define it in the class definition or something, but it all seems in order. So I'll post the code here in hopes that someone sees what's up with the render function or the bits surrounding it.
To be perfectly clear the exception is thrown on this line:
Title_Message = TTF_RenderText_Solid(font, "PONG", color);
//start code
/*CLASSES*/
class GameState
{
public:
virtual void events() = 0;
virtual void logic() = 0;
virtual void render() = 0;
virtual ~GameState(){};
};
class Button
{
public:
SDL_Rect button_clip[2];
SDL_Rect button;
SDL_Surface *button_sprite = NULL;
Button();
};
class Title : public GameState
{
private:
SDL_Surface *Title_Message = NULL;
SDL_Rect *clip;
Button Title_Button;
public:
void events();
void logic();
void render();
Title();
~Title();
};
/*FONTS*/
SDL_Color color = { 255, 255, 255 };
TTF_Font *font = NULL;
bool init()
{
//initialize all SDL subsystems
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
//set up screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
//check screen
if (screen == NULL)
{
return false;
}
//init TTF
if (TTF_Init() == -1)
{
return false;
}
//set window caption
SDL_WM_SetCaption("PONG", NULL);
//if evetything worked
return true;
}
//load files
bool load_files()
{
font = TTF_OpenFont("PIXELITE.ttf", 45);
if (font == NULL)
{
return false;
}
return true;
}
/*CLASS DEFINITIONS*/
Button::Button()
{
}
Title::Title()
{
Title_Message = TTF_RenderText_Solid(font, "PONG", color);
Title_Button.button_sprite = load_image("Start.png");
Title_Button.button.x = 200;
Title_Button.button.y = 350;
Title_Button.button.w = 100;
Title_Button.button.h = 50;
//clips not hover
Title_Button.button_clip[0].x = 0;
Title_Button.button_clip[0].y = 0;
Title_Button.button_clip[0].w = 100;
Title_Button.button_clip[0].h = 50;
//clips hover
Title_Button.button_clip[1].x = 0;
Title_Button.button_clip[1].y = 50;
Title_Button.button_clip[1].w = 100;
Title_Button.button_clip[1].h = 50;
}
Title::~Title()
{
SDL_FreeSurface(Title_Message);
SDL_FreeSurface(Title_Button.button_sprite);
}
void Title::events()
{
int x = 0;
int y = 0;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_MOUSEMOTION)
{
x = event.motion.x;
y = event.motion.y;
if ((x > Title_Button.button.x) && (x < (Title_Button.button.x + Title_Button.button.w)) && (y > Title_Button.button.y) && (y < (Title_Button.button.y + Title_Button.button.h)))
{
clip = &Title_Button.button_clip[1];
}
else
{
clip = &Title_Button.button_clip[0];
}
}
if (event.type == SDL_QUIT)
{
quit = true;
}
}
}
void Title::logic()
{
}
void Title::render()
{
apply_surface(Title_Button.button.x, Title_Button.button.y, Title_Button.button_sprite, screen, clip);
apply_surface((SCREEN_WIDTH - Title_Message->w) / 2, 100, Title_Message, screen);
}
Anybody got an idea? Thanks!
I will post my suggestions from the comments as an actual answer:
The trouble-causing line Title_Message = TTF_RenderText_Solid(font, "PONG", color); refers to the global variable font of type TTF_Font*. The line is also part of the constructor of the class Title.
main looks like this:
int main(int argc, char* args[])
{
//init SDL
init();
//load everything
load_files();
currentState = new Title;
//...
font is initialized to NULL at declaration, an actual object is assigned only in load_files() which is executed at the beginning of main before Title is the first time instantiated.
So load_files() has to assign a valid pointer to font, otherwise the next line in main will cause an access violation.
load_files() provides a return value depending on whether creating and assigning this object was successful. However main never checks for this value and thus it is not guaranteed that font is a valid pointer.
As knefcy pointed out the problem was a wrong filename in load_files().

SDL program crash on close - c0000005?

trying to just make a simple program to display the picture loaded into the system. If I type in an image name not found in the directory it returns and error to say it hasn't been found, but for some reason after this when I return 0; inside the main I get a crash.
I cannot find a way to solve it. Any help for what I'm doing wrong?
#include "SDL_Wrapper.h"
#include <iostream>
#include <string>
using namespace std;
class Image {
public:
Image();
~Image();
int loadImage();
int saveImage();
int outputImage();
protected:
int height, width;
string imageName;
SDL_Surface* displayWindow;
SDL_Surface* imageSurface;
SDL_Surface* tempSurface;
};
Image::Image() {
displayWindow = NULL;
imageSurface = NULL;
tempSurface = NULL;
}
Image::~Image() {
}
int Image::saveImage() {
return 0;
}
int Image::outputImage() {
return 0;
}
int Image::loadImage() {
if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
cout << "Error: Did not initialise correctly" << endl;
}
cout << "Enter the image name (and extension) you wish to use - ";
cin >> imageName;
imageSurface = LoadImage(imageName.c_str());
// Check if the image has been loaded correctly
if (imageSurface == NULL) {
imageSurface = NULL;
SDL_Quit();
cout << "Error: Picture not loaded/found" << endl;
return 1;
}
displayWindow = SDL_SetVideoMode(imageSurface->w, imageSurface->h, 32, SDL_SWSURFACE);
if (displayWindow == NULL) {
cout << "Error: displayWindow is blank, halting";
return 1;
}
SDL_WM_SetCaption("Image Preview", NULL);
SDL_BlitSurface(imageSurface, NULL, displayWindow, NULL);
if (SDL_Flip(displayWindow) == -1) {
cout << "Error: displayWindow did not flip correctly";
return 1;
}
SDL_Event event;
bool quit = false;
while (quit == false) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
}
SDL_FreeSurface(imageSurface);
SDL_Quit();
return 0;
}
void test()
{
Image img;
img.loadImage();
}
int main(int argc, char * argv[]) {
test();
return 0;
}
Edit:
Compiler tells me this -
Unhandled exception at 0x776015de in SDL_Display.exe: 0xC0000005: Access violation reading location 0x61d47bce.
In the 'Call Stack' it is on the line
- > SDL_Display.exe!std::_DebugHeapDelete<std::locale::facet>(std::locale::facet * _Ptr) Line 62 + 0xc bytes C++
Edit 2: LoadImage() function -
// Load Image
SDL_Surface* LoadImage(const char* ImageLocation)
{
// Initialize Variables
SDL_Surface *SDL_S_Return = NULL;
// Load Image
SDL_S_Return = IMG_Load(ImageLocation);
// If it hasn't been loaded...
if(SDL_S_Return == NULL)
{
// Send out an Error Message
fprintf(stderr, "Error: %s\n", IMG_GetError());
}
// Return the Surface (Will be NULL if file isn't loaded)
return SDL_S_Return;
}
your code is OK. it runs well and the only problem I can see is:
you did not convert loaded image to display format.
try this function:
SDL_Surface *loadImage(char *imageToLoad)
{
SDL_Surface *rawImage = NULL;
SDL_Surface *fixedImage = NULL;
//load image from file
rawImage = IMG_Load(imageToLoad);
//fix image's depth
fixedImage = SDL_DisplayFormat(rawImage);
//transparenty
Uint32 colorkey = SDL_MapRGB(fixedImage->format,0xff,0,0);
SDL_SetColorKey(fixedImage,SDL_SRCCOLORKEY,colorkey);
//free memory
SDL_FreeSurface(rawImage);
return fixedImage;
}