I was studying someone else's Pong code for an earlier version of SDL, and I'm trying to get it running with SDL2. Below is an excerpt from my code, which only loads the images. When this code is run, I get a window popping up telling me this:
Unhandled exception at 0x00A065AD in The Pong.exe: 0xC0000005: Access violation reading location 0x00000004. While it's debugging, it also points to this line:
optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);
The error list shows warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library.
I'm not sure what to make of all this. On top of that, the SDL window shows up, freezes, and sometimes won't close even after debugging has ended. (It tells me there's an access violation when I try.)
#include <string>
#include <SDL.h>
const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT = 475;
const int SCREEN_BPP = 2;
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
SDL_Surface *ball = NULL;
SDL_Surface *background = NULL;
SDL_Surface *paddleL = NULL;
SDL_Surface *paddleR = NULL;
SDL_Event event;
SDL_Surface *loadImage(std::string fileName)
{
SDL_Surface *loadedImage = NULL;
SDL_Surface *optimizedImage = NULL;
loadedImage = SDL_LoadBMP(fileName.c_str());
if (loadedImage != NULL)
{
optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);
SDL_FreeSurface(loadedImage);
if (optimizedImage != NULL)
{
SDL_SetColorKey(optimizedImage, SDL_TRUE,
SDL_MapRGB(optimizedImage->format, 255, 255, 255));
}
}
return optimizedImage;
}
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
return false;
window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH,
WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
return false;
return true;
}
bool loadFiles()
{
ball = loadImage("ball.bmp");
background = loadImage("background.bmp");
paddleL = loadImage("paddleRed.bmp");
paddleR = loadImage("paddleBlue.bmp");
if (ball == NULL)
return false;
if (background == NULL)
return false;
if (paddleL == NULL || paddleR == NULL)
return false;
return true;
}
int main(int argc, char* args[])
{
windowSurface = SDL_GetWindowSurface(window);
if (init() == false)
return 1;
if (loadFiles() == false)
return 1;
SDL_FreeSurface(windowSurface);
SDL_FreeSurface(ball);
SDL_FreeSurface(background);
SDL_FreeSurface(paddleL);
SDL_FreeSurface(paddleR);
windowSurface = ball = background = paddleL = paddleR = nullptr;
SDL_DestroyWindow(window);
window = nullptr;
SDL_Quit();
return 0;
}
You are calling
windowSurface = SDL_GetWindowSurface(window);
before
window = SDL_CreateWindow("Pong", SDL_WINDOWPOS_CENTERED,
so window will still be NULL, causing windowSurface to be NULL, causing windowSurface->format to cause a crash.
Related
I'm trying to test a simple SDL2 application. The app runs without any errors. However, no window shows up.
I'm using Ubuntu18.04 on a VMWare machine. I also tried to compile SDL from the source but got the same result. I am unsure if the cause of the problem is related to my OS or because of executing from a virtual machine.
Here is a simple application from docs (I just added SDL_GetNumDisplayModes to make sure the display mode is OK- returns 1)
// Using SDL and standard IO
#include <SDL2/SDL.h>
#include <stdio.h>
// Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char *args[])
{
// The window we'll be rendering to
SDL_Window *window = NULL;
// The surface contained by the window
SDL_Surface *screenSurface = NULL;
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
int res = SDL_GetNumDisplayModes(0);
printf("SDL_GetNumDisplayModes: %d\r\n", res);
// Create window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
// Get window surface
screenSurface = SDL_GetWindowSurface(window);
// Fill the surface white
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));
// Update the surface
SDL_UpdateWindowSurface(window);
// Hack to get window to stay up
SDL_Event e;
bool quit = false;
while (quit == false)
{
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
{
quit = true;
}
}
}
}
}
// Destroy window
SDL_DestroyWindow(window);
// Quit SDL subsystems
SDL_Quit();
return 0;
}
I have tried looking all over the place for an answer but to no avail.
in debugger mode it worked fine but when i put it in release mode it give me this
Unhandled exception at 0x00DC1814 in sdl project.exe: 0xC0000005: Access violation reading location 0x00000000.
i have my debugger and release mode include and library the same, even my subsystems are the same. here is my code, i have shorten it by a bit
SDL_Surface *loadimage();
struct picture
{
int maxframe;
SDL_Surface *surface = NULL;
SDL_Rect rect;
std::string filepath;
};
SDL_Surface *background = NULL;
SDL_Surface *backbuffer = NULL;
SDL_Surface *holder = NULL;
std::vector<picture *> veck;
int main(int argc, char* argu[]){
background = SDL_LoadBMP("pics/bac.bmp");
if (background == NULL){
return false;
}
int height = background->h;
int width = background->w;
init_testprogram();
backbuffer = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE);
SDL_WM_SetCaption("Yamada's first window", NULL);
//this was here to test if i could format a surface more then once in
//the same format kept in just in case
holder = SDL_DisplayFormat(background);
background = SDL_DisplayFormat(holder);
SDL_FreeSurface(holder);
//this is where i get the error
veck[0]->surface = loadimage();
veck[0]->rect.w = veck[0]->surface->w;
veck[0]->rect.h = veck[0]->surface->h;
//if commented out this is where i get my second error
veck.push_back(new picture);
veck[1]->rect.x = 39;
veck[1]->rect.y = 49;
veck[1]->surface = veck[0]->surface;
veck[1]->rect.w = veck[0]->surface->w;
veck[1]->rect.h = veck[0]->surface->h;
veck[0]->rect.x = 500;
veck[0]->rect.y = 200;
//printing to screan
TTF_Font *font = NULL;
Mix_Chunk *sound = NULL;
picture *picture1;
//if commented out again this is where i get my third error in sound
sound = Mix_LoadWAV("sound/walking in grass.wav");
font = TTF_OpenFont("fonts/CaviarDreams.ttf", 100);
while (programisrunning()){
//do SDL stuff herre
}
SDL_Delay(3000);
SDL_Quit();
TTF_Quit();
Mix_CloseAudio();
int t;
std::cin >> t;
return 0;
}
/////definitions
SDL_Surface *loadimage(){
veck.push_back(new picture);
SDL_Surface* rawimage = NULL;
SDL_Surface* processedimage = NULL;
veck[0]->filepath = "pics/walk 3.png";
rawimage = IMG_Load(veck[0]->filepath.c_str());
if (rawimage == NULL){
errorreport("image 'walk 3.png' failed to load\n");
return false;
}
processedimage = SDL_DisplayFormat(rawimage);
SDL_FreeSurface(rawimage);
if (processedimage == NULL){
errorreport("image 'walk 3.png' failed to process\n");
return false;
}
Uint32 colorkey = SDL_MapRGB(processedimage->format, 255, 255, 255);
SDL_SetColorKey(processedimage, SDL_SRCCOLORKEY, colorkey);
// EDIt
if (processedimage == NULL)
errorreport("ERRRORORROROOR BUT WHY\n");
return processedimage;
}
i know its not in the best way of doing things but this is my test project for doing stuff in sdl. if i comment out the hole veck[0] thing then i get the same error but at further down in veck.pushback() and if i comment out all the vecks then i get the error at sound. i am using visual studio exress 2013 if that helps at all. i don't understand what i am doing wrong.
i did cut out stuff i thought was pointless to add here
You have undefined behavior in veck[0]->surface = loadimage(); since veck[0] won't get an object until loadimage() has executed.
There's no guarantee that loadimage() will be called before veck[0] is evaluated.
I'm using SDL 2.0 with C++ for 2D graphics, compressed image format loading, sound playback and so on. Consider the following code:
int main(int argc, char *args[])
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
SDL_Window *pWindow = SDL_CreateWindow("Access Violation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1920, 1080, SDL_WINDOW_FULLSCREEN);
SDL_Renderer *pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
Mix_Init(0);
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
Mix_Music *pMusic = Mix_LoadMUS("music.wav");
TTF_Init();
TTF_Font *pFont = TTF_OpenFont("font.ttf", 28);
bool quit = false;
SDL_Event ev;
while(!quit)
{
while(SDL_PollEvent(&ev) != 0)
{
switch(ev.type)
{
case SDL_QUIT:
quit = true;
break;
}
}
SDL_SetRenderDrawColor(pRenderer, 255, 255, 255, 255);
SDL_RenderClear(pRenderer);
for(int i = 0; i < 864; i++)
{
SDL_Color clr = { 0, 0, 0 };
SDL_Surface *pSurface = TTF_RenderText_Solid(pFont, "Hey!", clr);
SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
SDL_Rect dstrect = { (int)(i/27) * 60, (i%27)*40, pSurface->w, pSurface->h };
SDL_RenderCopy(pRenderer, pTexture, 0, &dstrect);
SDL_DestroyTexture(pTexture);
SDL_FreeSurface(pSurface);
}
SDL_RenderPresent(pRenderer);
}
TTF_CloseFont(pFont);
Mix_FreeMusic(pMusic);
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
Mix_CloseAudio();
Mix_Quit();
IMG_Quit();
TTF_Quit();
SDL_Quit();
return 0;
}
What this basically does is that it just initializes SDL, loads a music, loads a font, and fills continuously the whole screen with text. Fine.
But!
If I add this line
...
SDL_Event ev;
Mix_PlayMusic(pMusic, 0);
while(!quit)
...
right here, text redrawing in the cycle
for(int i = 0; i < 864; i++)
{
...
}
starts to behave unpredictably. One of the SDL's function will shoot an access violation, after some time - between 1 and 30 seconds after start. On the other hand, would I omit text redrawing, music is playing fine.
Any ideas? Of course, all return values are checked. I've omitted checks because of the clarity of the code.
EDIT: Typos.
So I'm learning C++ with SDL (on Visual Studio 2013). I'm following Lazy Foo's tutorials (specifically: http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php).
My image won't render. In contrast to the tutorial (which works) I do not have global surface variables. Instead I declared them in the main and passed the pointers around.
Code:
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 480;
//SDL init.
bool initialiseSDL(SDL_Window* gWindow, SDL_Surface* gWindowSurface)
{
bool success = true;
/*SDL_Init() initisalises SDL library. Returning 0 or less signifies an error.
SDL_INIT_VIDEO flag refers to graphics sub system.*/
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialise. SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create the window
gWindow = SDL_CreateWindow("Asteroids", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (gWindow == NULL)
{
printf("Could not create window. SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Get the window surface.
gWindowSurface = SDL_GetWindowSurface(gWindow);
}
}
return success;
}
bool loadMedia(SDL_Surface* surface, std::string path)
{
//Success flag
bool success = true;
surface = SDL_LoadBMP(path.c_str());
if (surface == NULL)
{
printf("SDL surface failed to load. SDL Error: %s\n", SDL_GetError());
success = false;
}
return success;
}
void close()
{
}
int main(int argc, char* argv[])
{
SDL_Window* gWindow = NULL;
SDL_Surface* gWindowSurface = NULL;
SDL_Surface* gImageSurface = NULL;
if (!initialiseSDL(gWindow, gWindowSurface))
{
printf("Failed to initialise.\n");
}
else
{
if (!loadMedia(gImageSurface, "hw.bmp"))
{
printf("Failed to load inital media.");
}
else
{
//Apply the image
SDL_BlitSurface(gImageSurface, NULL, gWindowSurface, NULL);
//Update the surface
SDL_UpdateWindowSurface(gWindow);
//Wait two seconds
SDL_Delay(2000);
}
}
return 0;
}
Your program exhibits undefined behavior, because the pointers inside the main function are not initialized.
When you pass them to the initialiseSDL function you pass them by value, meaning they are copied and the function only operates on the copies and not the original pointers, which will still be uninitialized after the call.
What you need to do is to pass the pointers by reference instead:
bool initialiseSDL(SDL_Window*& gWindow, SDL_Surface*& gWindowSurface)
You of course need to do the same with the loadMedia function.
I've been following the lazy foo SDL tutorials and have already hit a road block in lesson 2. My code is exactly what he wants, yet i keep getting the same errors whenever i'm trying to blit the following images:
Unhandled exception at 0x68126030 in SDLtest.exe: 0xC0000005: Access violation reading location 0x00000004.
Here is the following code that is constantly producing such errors:
#include "SDL.h"
#include <string>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *load_image(std::string filename)
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
//load the image
loadedImage = SDL_LoadBMP( filename.c_str() );
if (loadedImage != NULL)
{
optimizedImage = SDL_DisplayFormat(loadedImage);
SDL_FreeSurface(loadedImage);
}
return optimizedImage;
}
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
//blit the surface
SDL_BlitSurface(source, NULL, destination, &offset);
}
int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
if (screen = NULL)
{
return 1;
}
SDL_WM_SetCaption("Hello World",NULL);
//loading images
message = load_image("hello.bmp");
background = load_image("background.bmp");
//image blitting
apply_surface(0,0,background,screen);
apply_surface(320,0,background,screen);
apply_surface(0,240,background,screen);
apply_surface(320,240,background,screen);
apply_surface(180,140,message,screen);
if (SDL_Flip(screen) == -1)
{
return 1;
}
SDL_Delay(2000);
SDL_FreeSurface(message);
SDL_FreeSurface(background);
SDL_Quit();
return 0;
}
The error Access violation reading location 0x00000004 is saying that you are dereferencing a pointer whose value is 4, instead of something real.
The easiest way to track this down is to run under a debugger, and see what line causes the problem. Then you can backtrack to figure out where the pointer's value got messed up. Then you may find an error like Bert pointed out.
Replace the line
if(screen = NULL)
with
if(screen == NULL)