SDL2 access violation reading location 0x00000000 in IMG_Load function

-2

I have recently been working on an SDL2 project in Visual C++ when I encountered an exception being thrown in my program, which I believe is caused by another function being called. I am working in multiple files so I will post the code from each file that I believe could be contributing to the problem:

(In Game.h):

#pragma once

#include "SDL.h"
#include "SDL_image.h"
#include <iostream>
#include <vector>

class ColliderComponent;

class Game
{
public:
    Game();
    ~Game();

void init(const char* title, int width, int height, bool fullscreen);

void handleEvents();
void update();
bool running() { return isRunning; }
void render();
void clean();

static void AddTile(int id, int x, int y);
static SDL_Renderer *renderer;
static SDL_Event event;
static std::vector<ColliderComponent*> colliders;

private:
    bool isRunning = false;
    int cnt = 0;
    SDL_Window *window;
};

(In Game.cpp):

#include "Game.h"
#include "TextureManager.h"
#include "Map.h"
#include "ECS/Components.h"
#include "Vector2D.h"
#include "Collision.h"

Map* overworld; //Create a map object
SDL_Event Game::event; //Create an event object
SDL_Renderer* Game::renderer = nullptr; //Create the renderer

Manager manager; //Create a manager object

std::vector<ColliderComponent*> Game::colliders; //Create the collision handler

auto& Character1(manager.addEntity()); //Create the Character entity
auto& wall(manager.addEntity()); //Create a wall entity

Game::Game()
{}

Game::~Game()
{}

void Game::init(const char* title, int width, int height, bool fullscreen)
{
int flags = 0;

if (fullscreen) //If fullscreen is true set the window to fullscreen mode
{
    flags = SDL_WINDOW_FULLSCREEN;
}

if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
    window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags);
    renderer = SDL_CreateRenderer(window, -1, 0);
    if (renderer)
    {
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    }

    isRunning = true;
}

overworld = new Map(); //Create Map object

Map::LoadMap("assets/Overworld3.map", 5, 5); //Load map

//Add components to Character1:
Character1.addComponent<TransformComponent>(64.0f, 64.0f);
Character1.addComponent<SpriteComponent>("assets/Character.png");
Character1.addComponent<KeyboardController>();
Character1.addComponent<ColliderComponent>("Character1");

//Add components to wall:
wall.addComponent<TransformComponent>(189.0f, 189.0f, 64, 128, 1);
wall.addComponent<SpriteComponent>("assets/Ocean1.png");
wall.addComponent<ColliderComponent>("wall");
}

//Handle any events that may happen:
void Game::handleEvents()
{
SDL_PollEvent(&event);

switch (event.type)
{
case SDL_QUIT :
    isRunning = false;
    break;
default:
    break;
}
}

//Update the game:
void Game::update()
{
manager.refresh();
manager.update();

for (auto cc : colliders) {
    Collision::AABB(Character1.getComponent<ColliderComponent>(), *cc);
    }
}

//Render the sprites:
void Game::render()
{
SDL_RenderClear(renderer);
manager.draw();
SDL_RenderPresent(renderer);
}

//Clean up the game:
void Game::clean()
{
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
}

//Add a tile to the map:
void Game::AddTile(int id, int x, int y) {
auto& tile(manager.addEntity());
tile.addComponent<TileComponent>(x, y, 64, 64, id);
}

(In Map.h):

#pragma once
#include <string>

class Map {
public:

Map();
~Map();

static void LoadMap(std::string path, int sizeX, int sizeY);

private:

};

(In Map.cpp):

#include "Map.h"
#include "Game.h"
#include <fstream>

Map::Map() {
}

Map::~Map() {
}

void Map::LoadMap(std::string path, int sizeX, int sizeY) {
    char tile;
    std::fstream mapFile;
    mapFile.open(path);

for (int y = 0; y < sizeY; y++) {
    for (int x = 0; x < sizeX; x++) {
        mapFile.get(tile);
        Game::AddTile(atoi(&tile), x * 64, y * 64);
        mapFile.ignore();
        }
    }
//Run twice to mimic the effect of multiple map layers
for (int y = 0; y < sizeY; y++) {
    for (int x = 0; x < sizeX; x++) {
        mapFile.get(tile);
        Game::AddTile(atoi(&tile), x * 64, y * 64);
        mapFile.ignore();
    }
}

mapFile.close();
}

(In TextureManager.h):

#pragma once

#include "Game.h"

class TextureManager {
public:
static SDL_Texture* LoadTexture(const char* texture);
static void Draw(SDL_Texture* tex, SDL_Rect src, SDL_Rect dest);
};

(In TextureManager.cpp):

#include "TextureManager.h"

SDL_Texture* TextureManager::LoadTexture(const char* texture) {

    SDL_Surface* tempSurface = IMG_Load(texture);
    SDL_Texture* tex = SDL_CreateTextureFromSurface(Game::renderer, tempSurface);
    SDL_FreeSurface(tempSurface);

    return tex;
}

void TextureManager::Draw(SDL_Texture* tex, SDL_Rect src, SDL_Rect dest) {
SDL_RenderCopy(Game::renderer, tex, &src, &dest);
}

The exception occurs at the line: SDL_Surface* tempSurface = IMG_Load(texture); It gives this message: Exception thrown at 0x6C7C1179 (SDL2.dll) in UBitEngine.exe: 0xC0000005: Access violation reading location 0x00000000. I believe the problem is caused by the line: Map::LoadMap("assets/Overworld3.map", 5, 5); Since if I comment it out, the program runs correctly. However, I have no idea why this line would cause an error. This is what the Overworld3.map file looks like (It was originally a json file):

1, 1, 1, 1, 1

1, 1, 1, 1, 1

1, 1, 1, 1, 1

1, 1, 1, 1, 1

1, 1, 1, 1, 1

Which corresponds to a map made entirely out of grass tiles. I am 99% sure that this problem is not caused by not having access to the necessary dlls, as I have SDL2.dll, SDL2_image.dll, libpng16-16.dll, and zlib1.dll both in the debug folder and the folder containing the project. If anyone has any suggestions for fixing this, please let me know.

c++
visual-c++
visual-studio-2017
sdl-2
asked on Stack Overflow Jul 17, 2018 by CodyFG

1 Answer

0

The error lied in the file. The program was written to read from the file and see a number, and depending on the number, display a certain tile on the map. Then, it expected to find a comma, which it would ignore. After that, it expected to see another number, but since each number had a space in between it, it received a blank character as the value. It would then send this to a tile component which would return a certain value for the path depending on the number it found. However, it received a " " as the character rather than a number. Because of this, no value was given to the path, and therefore it was NULL. This is what caused the null pointer exception. Thank you to everyone who helped me figure this out!

answered on Stack Overflow Jul 19, 2018 by CodyFG

User contributions licensed under CC BY-SA 3.0