Showing posts with label sdl-2. Show all posts
Showing posts with label sdl-2. Show all posts

Saturday, August 26, 2017

Calling SDL “IMG_Load” a second time results in a “EXC_BAD_ACCESS (code=EXC_I386_GPFLT)”

Leave a Comment

Im running this on MacOS 10.12 using Xcode 8.3.3 with SDL2 installed via Homebrew as Dylibs.

Below is some slightly modified sample code from lazy foo.

I just added a second texture gTexture2 and the function loadMedia2 to be able to reproduce the issue. The second time IMG_Load is executed it crashes with the following message:

EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 

Searching on how to solve a "General Protection Fault" problem did also not get me further, the crash seems to happen inside SDL. I probably really misunderstand here something that leads to this issue and would really welcome any help.

enter image description here

The really confusing thing is, it does not crash always, only about 2 of 3 times.

The crash seem to happen inside SDL_AllocFormat_REAL ():

enter image description here

Here is the code sample.

/*This source code copyrighted by Lazy Foo' Productions (2004-2015)  and may not be redistributed without written permission.*/  //Using SDL, SDL_image, standard IO, and strings #include <SDL.h> #include <SDL_image.h> #include <stdio.h> #include <string>  //Screen dimension constants const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480;  //Starts up SDL and creates window bool init();  //Loads media bool loadMedia();  //Frees media and shuts down SDL void close();  //Loads individual image as texture SDL_Texture* loadTexture( std::string path );  //The window we'll be rendering to SDL_Window* gWindow = NULL;  //The window renderer SDL_Renderer* gRenderer = NULL;  //Current displayed texture SDL_Texture* gTexture = NULL; SDL_Texture* gTexture2 = 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 );         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 );                  //Initialize PNG loading                 int imgFlags = IMG_INIT_PNG;                 if( !( IMG_Init( imgFlags ) & imgFlags ) )                 {                     printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );                     success = false;                 }             }         }     }      return success; }  bool loadMedia() {     //Loading success flag     bool success = true;      //Load PNG texture     gTexture = loadTexture( "../assets/player.png" );     if( gTexture == NULL )     {         printf( "Failed to load texture image!\n" );         success = false;     }      return success; }  bool loadMedia2() {     //Loading success flag     bool success = true;      //Load PNG texture     gTexture2 = loadTexture( "../assets/scene_main/background.png" );     if( gTexture == NULL )     {         printf( "Failed to load texture image!\n" );         success = false;     }      return success; }  void close() {     //Free loaded image     SDL_DestroyTexture( gTexture );     SDL_DestroyTexture( gTexture2 );     gTexture = NULL;     gTexture2 = NULL;              //Destroy window     SDL_DestroyRenderer( gRenderer );     SDL_DestroyWindow( gWindow );     gWindow = NULL;     gRenderer = NULL;      //Quit SDL subsystems     IMG_Quit();     SDL_Quit(); }  SDL_Texture* loadTexture( std::string path ) {     //The final texture     SDL_Texture* newTexture = NULL;      //Load image at specified path     SDL_Surface* loadedSurface = IMG_Load( path.c_str() );     if( loadedSurface == NULL )     {         printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );     }     else     {         //Create texture from surface pixels         newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );         if( newTexture == NULL )         {             printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );         }          //Get rid of old loaded surface         SDL_FreeSurface( loadedSurface );     }      return newTexture; }  int main( int argc, char* args[] ) {     //Start up SDL and create window     if( !init() )     {         printf( "Failed to initialize!\n" );     }     else     {         //Load media         if( !loadMedia() || !loadMedia2() )         {             printf( "Failed to load media!\n" );         }         else         {                //Main loop flag             bool quit = false;              //Event handler             SDL_Event e;              //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;                     }                 }                  //Clear screen                 SDL_RenderClear( gRenderer );                  //Render texture to screen                 SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );                  //Update screen                 SDL_RenderPresent( gRenderer );             }         }     }      //Free resources and close SDL     close();      return 0; }    

Little Update:

  • I've tried it on windows, there it runs completely fine. So I guess the issue is related to MacOs.

  • I already tried to reinstall all libraries.

  • I'm using C++14.

The solution

Thanks to @Sahib Yar he pointed out to try to put the images in the same directory. Which resolves the issue.

Now I would really love an explanation why we can't load images from multiple directories using SDL on MacOS. Is that just a bug or known thing.

1 Answers

Answers 1

It seems that you are not destroying texture2 that is not needed.

SDL_DestroyTexture( gTexture ); SDL_DestroyTexture( gTexture2 );  gTexture = NULL; gTexture2 = NULL; 

In this lazyfoo tutorial, it is mentioned that

In our clean up function, we have to remember to deallocate our textures using SDL_DestroyTexture.

Edit 1:

Try to put all your images in the same directory.

Edit 2:

It is not related to directory in MacOS From this tutorial, it seems like compiler is doing some optimization with std::string path as the std::string is mutable. Try to clear the std::string path object at end of function to clear up all the memory reserved by its objects.

add this line.

std::string().swap(path); 

Your issue is a dangling pointer. EXC_BAD_ACCESS is the CPU moaning that you are addressing non-existent memory or memory which is outside of your access rights area. The cause is a lack of reatainment of an object which causes early deallocation and then is overwritten. At which time (which may be delayed), the pointer will point to garbage whose dereference causes an EXC_BAD_ACCESS to be thrown.

Read More

Friday, June 10, 2016

Play .ogg file with SDL_mixer in Edge and Safari (emscripten)

Leave a Comment

I've created a program, which uses (SDL2) SDL_mixer to play .ogg sound files.

It works in Chrome, Firefox and Opera. But it is not working in MS Edge, and Safari, because the lack of ogg sound support.

I've added this command to the emcc, which should fix this issue:

-s USE_OGG=1 

But it is still not working.

How is it possible to make .ogg sound files work in Edge (and Safari)?

1 Answers

Answers 1

You can't.

At the moment of this writing, both Safari and MS Edge won't support .ogg, as you mentioned.

Since Emscripten compiles to JavaScript, you'd better find a way to make you code accept another audio extension (fallback) supported by Safari and MS Edge, such as .mp3 or .m4a AAC (which is an audio component of mp4).

Read More

Thursday, April 14, 2016

How to ensure an SDL2 fullscreen window is ready with Python (pysdl2)?

Leave a Comment

When generating a new fullscreen window, vis-a-vis:

sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) window = sdl2.ext.Window('win_name', (x_size, y_size), (0, 0), <<flags>>) 

If I begin loading resources, or blitting to the graphics buffer immediately, the window may or may not be ready; the time this takes seems entirely contingent on the interim processing overhead.

Is there a callback or some means of knowing that the screen is fully ready? I've gone through the pysdl2 docs and found nothing promising, but I get lost in the sdl2 docs pretty quickly because I'm not a C programmer.

1 Answers

Answers 1

No, there is no callback to know if the windows is ready because there is no need for it.

When the sdl2.ext.Window() returns, you're guaranteed that the window itself is ready.

However, graphics that you put in that window might not be ready and in that case, you should load graphics and call window.show() after it has been loaded.

Read More