1

I am using the SDL2 2.0.3 library with the SDL_image library 2.0.0 in Visual C++ 2010 Express. I am utilizing the SDL_image library to load a variety of PNG and JPEG files from a resources folder. While the library initializes without any errors and loads BMP and JPEG files, it breaks when given a PNG file.

"Unhandled exception at 0x00000000 in appname.exe: 0xC0000005: Access violation."

Inside of my texture manager, (an object that stores and manages textures for the program), is a function to load a texture from a given file name string. Here is the code, including the commented line I used before implementing SDL_image to do the loading. It is within the line bitmapSurface = IMG_Load(... that the exception above is thrown.

/**
 * Attempts to load a given image file and reports to the console any failures
 * 
 * @param fileName The exact file name of the resource to be loaded
 * @return The SDL_Texture loaded from the given fileName
 */
SDL_Texture* TextureManager::loadTexture(string fileName)
{
    //Create our surface in RAM
    SDL_Surface *bitmapSurface = NULL;
    //bitmapSurface = SDL_LoadBMP(fileName.c_str()); //OLD METHOD; standard SDL, BMP only
    bitmapSurface = IMG_Load(fileName.c_str());      //NEW METHOD; SDL_image lib, many formats

    //Verify it exists
    if (bitmapSurface == NULL)
        cout << "Image resource not loaded: " << fileName << " Message: " << IMG_GetError() << endl;

    //Create a texture in VRAM from the surface
    SDL_Texture *bitmapTexture = NULL;
    bitmapTexture = SDL_CreateTextureFromSurface(this->renderer, bitmapSurface);

    //Verify it exists
    if (bitmapTexture == NULL)
        cout << "Failed to create texture: " << fileName << endl;

    return bitmapTexture;
}

Call Stack:

    00000000()  
    SDL2_image.dll!6a887a01()   
    [Frames below may be incorrect and/or missing, no symbols loaded for SDL2_image.dll]    
    SDL2.dll!6c77da4b()     
    SDL2_image.dll!6a88792e()   
    SDL2_image.dll!6a881693()   
    SDL2_image.dll!6a8817e9()   
> appname.exe!TextureManager::loadTexture(std::basic_string<char,std::char_traits<char>,std::allocator<char> > fileName)  Line 143 + 0xe bytes  C++
    00daf5e0()  

Here is the constructor for my TextureManager:

/**
 * Creates a new TextureManager with the current SDL_Renderer
 * 
 * @param renderer The current renderer instance of the current graphic window
 */ 
TextureManager::TextureManager(SDL_Renderer* renderer)
{
    //Assign our renderer link
    this->renderer = renderer;

    //Create the vector to hold textures
    this->textures = new vector<Texture*>();

    //SDL_image initialization
    int flags   = IMG_INIT_JPG|IMG_INIT_PNG;
    int initted = IMG_Init(flags); //Use IMG_Quit(); at closing

    if(initted&flags != flags)
    {
        //Handle error
        printf("IMG_Init: Failed to init required jpg and png support!\n");
        printf("IMG_Init: %s\n", IMG_GetError());
    }
    else
    {
        cout << "SDL_Image initialized for JPEG and PNG support" << endl;
    }
}

For your information, I am using Windows 10 x64, which is up to date. Graphics drivers for dual NVidia GTX 550ti are up to date as well. All DLL files (including the pnglib dll) are in the debug folder and do load. If I remove the DLL file from the program, the image fails to load and provides the message as coded above for NULL surfaces. No exceptions occur.

Question summary: Why is this exception thrown, why is it only thrown for PNG files, and how can I trace it when the call stack's details end at my call that appears to work properly? Am I doing something wrong, or is there a configuration step I may have missed?

EDIT: Thanks to @Nandu I have recompiled the DLL SDL_image, and got a better call stack output here:

    00000000()  
> SDL2_image.dll!IMG_LoadPNG_RW(SDL_RWops * src)  Line 375 + 0x11 bytes C
    SDL2_image.dll!IMG_LoadTyped_RW(SDL_RWops * src, int freesrc, const char * type)  Line 193 + 0x12 bytes C
    SDL2_image.dll!IMG_Load(const char * file)  Line 134 + 0xf bytes    C
    appname.exe!TextureManager::loadTexture(std::basic_string<char,std::char_traits<char>,std::allocator<char> > fileName)  Line 143 + 0xe bytes    C++
    appname.exe!TextureManager::loadFromDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > relPath)  Line 117 + 0x73 bytes  C++
    appname.exe!SDL_main(int argc, char * * argv)  Line 31  C++
    appname.exe!main(int argc, char * * argv)  Line 140 + 0xd bytes C
    appname.exe!__tmainCRTStartup()  Line 555 + 0x19 bytes  C
    appname.exe!mainCRTStartup()  Line 371  C
    kernel32.dll!77963744()     
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
    ntdll.dll!77c3a064()    
    ntdll.dll!77c3a02f() 

This suggests the problem is occurring on line 374 of IMG_png.c:

 /* Create the PNG loading context structure */
    png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING,
                      NULL,NULL,NULL);

VS reports that lib is NULL at this time, which would explain the error! The question becomes, why is it NULL? It seems this code should be doing a check for that, but nonetheless, nobody else seems to having this problem on the almighty internet.

Bit Fracture
  • 651
  • 1
  • 9
  • 24
  • 1
    You have code to check for a NULL return value, but your code continues as if nothing is wrong. `//Verify it exists if (bitmapSurface == NULL)` – PaulMcKenzie Nov 11 '15 at 19:08
  • 1
    do u own the DLL file? if yes, rebuild it with optimization turned off (also turn off optimization for application). With symbols built-into dll's you'd be able to gather call stack and origin of this crash. – Nandu Nov 11 '15 at 19:10
  • @PaulMcKenzie Yes, my code further on is resistant to NULL textures, I just want the warning. – Bit Fracture Nov 11 '15 at 19:15
  • @Nandu I've never done that before, but I'll give it a shot. If you have any advice or tutorials, they would be much appreciated. – Bit Fracture Nov 11 '15 at 19:16
  • `this->textures = new vector();` There is no need for `new`. Just have a member `vector`. You also are passing a pointer to the constructor and it isn't clear which entity actually owns the pointer or who is responsible for cleanup. Bottom line is that there are a multitude of things that can go wrong with your program, given the way you've designed things. – PaulMcKenzie Nov 11 '15 at 19:16
  • @PaulMcKenzie Thank you for the advice, but I need the `new` or it won't compile. I am new to C++, so there are problems which I am working through as I learn more, but they don't appear to be what is causing this problem. – Bit Fracture Nov 11 '15 at 19:19
  • @Nandu I built the DLL and got a better stack trace. I will update the original post. Thank you! – Bit Fracture Nov 11 '15 at 19:48
  • @BitFracture *Thank you for the advice, but I need the new or it won't compile.* That is because you declared it as a pointer. – PaulMcKenzie Nov 11 '15 at 19:52
  • @PaulMcKenzie I am sorry if I don't understand your point. I meant for it to be a pointer, but if there is a reason I shouldn't, please direct me towards some documentation explaining otherwise. You're probably totally correct, but I don't see how it contributes to this topic. Thank you. – Bit Fracture Nov 11 '15 at 19:58
  • @BitFracture is the libpng library available in your project for sdl to use? – yms Nov 11 '15 at 20:04
  • 1
    I would say that your libpng library is not loading properly, in such scenario I would try building the whole thing from source code and debugging it. – yms Nov 11 '15 at 20:15
  • @yms The DLL is available, and when I remove it, there are no exceptions thrown, and my code reports the NULL in both cases as it should. The lib file is not present. The SDL_image source appears to directly reference the libpng source code. The library was not distributed with additional lib files. – Bit Fracture Nov 11 '15 at 20:16

1 Answers1

2

Thank you all very much for you help, but the problem, as usual, was rather obvious! As noted here by @Gigi: SDL_Image IMG_Load fails on png with: "Failed loading libpng16-16.dll:"

I suggest you try including all the rest - there may be a dependency that you and I are not aware of. In fact I just checked, and libpng requires zlib: libpng.org/pub/png/libpng.html

I'm not sure why my original search or suggestions didn't bring that post up.

I originally excluded the DLLs for other file formats I wasn't using (or initializing in my code), but once I included the zlib DLL, bingo. PNGs load exactly as expected.

Community
  • 1
  • 1
Bit Fracture
  • 651
  • 1
  • 9
  • 24