Search code examples
c++sdl

SDL_Image library crashes programs or makes them misbehave


I have an sdl2 program which works fine on my machine(win xp 32bit). When i send it to my friend (win 10 64bit), the program displays the SetRenderDrawColor and crashes after a few seconds. This program uses SDL2 and SDL2_Image.

I then copied a barebones sdl2 program from a website. And it works on both of our computers.

I then modified the program to use IMG_Load from the SDL_Image library, which again, works fine on my end, but this time, doesn't crash, but instead just displays the set RenderDrawColor and but not the loaded image and closes after the SDL_Delay finishes on my friends computer.

The compile command that I used is:

g++ main.cpp -lSDL2 -lSDL2main -lSDL_Image -static-libgcc -static-libstdc++ -o main.exe

Also while I'm at it, I'll say that no sdl2 program works on my win7 nor my win xp computers if I don't have the #define SDL_MAIN_HANDLED. However no tutorial that I ever came across said that I need to use such a thing.

Any help?

Edit: Posting barebone program code

#define SDL_MAIN_HANDLED

#include <SDL2/SDL.h>
#include <SDL2/SDL_Image.h>
#include <iostream>

int main( int argc, char* args[] )
{
    int posX = 100;
    int posY = 200;
    int sizeX = 300;
    int sizeY = 400;
    SDL_Window* window;
    SDL_Renderer* renderer;
    SDL_Event event;

    // Initialize SDL
    // ==========================================================
    if ( SDL_Init( SDL_INIT_EVERYTHING ) != 0 )
    {
        // Something failed, print error and exit.
        std::cout << " Failed to initialize SDL : " << SDL_GetError() << std::endl;
        return -1;
    }

    // Initialize SDL_Image
    int flags = IMG_INIT_JPG|IMG_INIT_PNG;
    int initted = IMG_Init(flags);

    if((initted&flags) != flags)
    {
      printf("IMG_Init: Failed to init required jpg and png support!\n");
      printf("IMG_Init: %s\n", IMG_GetError());
    }

    // Create and init the window
    // ==========================================================
    window = SDL_CreateWindow( "test", posX, posY, sizeX, sizeY, 0 );

    if ( window == nullptr )
    {
        std::cout << "Failed to create window : " << SDL_GetError();
        return -1;
    }

    // Create and init the renderer
    // ==========================================================
    renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

    if ( renderer == nullptr )
    {
        std::cout << "Failed to create renderer : " << SDL_GetError();
        return -1;
    }

    // Render something
    // ==========================================================    
    // Load image
    SDL_Surface* loader = IMG_Load("background.jpg");
    SDL_Texture* sprite = SDL_CreateTextureFromSurface(renderer, loader);

    if(loader == NULL)
    {
       std::cout << "Loader failed!" << std::endl << std::endl;
       IMG_GetError();
    }
    // Set size of renderer to the same as window
    SDL_RenderSetLogicalSize( renderer, sizeX, sizeY );

    // Set color of renderer to red
    SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 );

    // Clear the window and make it all red
    SDL_RenderClear( renderer );

    // Draw image
    SDL_RenderCopy(renderer, sprite, 0, 0);

    // Render the changes above ( which up until now had just happened behind the scenes )
    SDL_RenderPresent( renderer);

    // Pause program so that the window doesn't disappear at once.

    while(true)
    {
      SDL_PollEvent(&event);

      if(event.type == SDL_QUIT) return 0;

      SDL_Delay( 10 );
    }

    return 0;
}

Solution

  • The problem was solved by adding libpng16-16.dll and zlib1.dll from the MingGW installation into the distributed folder.

    If anyone else has this issue, the total of .dlls that were needed for this to work were:

    SDL2.dll | SDL2_Image.dll | libwinpthread-1.dll | libpng16-16.dll| zlib1.dll.