I've been getting this read access violation exception for hours now and I can't for the life of me find out what it is. It was working before now I don't know what I've changed to cause it.
I've limited the problem down to my Level class or how LevelManager is created I think. Using VC++ debugger I've watched the value of my GameEngine* pointer that gets passed to LevelManager upon construction using the this pointer, when Level::Load() is called the debugger reveals that it can no longer watch the engine pointer saying it's inaccesible memory. Low and behold when I step to the engine pointer that tries to call a function the exception occurs with the message "this is nullptr":
GameEngine constructor
1 2
|
GameEngine::GameEngine(std::string name) : game_name(name), tileset_manager(this), level_manager(this)
{
|
Constructor for LevelManager and Load function where Level::Load is called:
1 2 3 4 5 6 7 8 9 10
|
LevelManager::LevelManager(GameEngine* e): engine(e) {} // engine is of GameEngine
void LevelManager::Load(std::string id, std::string filename)
{
if (engine == nullptr) std::cout << "Engine nullptr\n"; // Nope, not here
levels[id] = std::shared_ptr<Level>(new Level(engine));
current_level->LoadLevel(filename);
current_level = levels[id];
}
|
Level constructor
1 2 3 4 5
|
Level::Level(GameEngine* e) : engine(e)
{
for (size_t i = 0; i < LayerType::LAYER_SIZE; i++) // engine seems to be assigned to e here
level.push_back(std::vector<TileObj>());
}
|
Level::Load
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
bool Level::LoadLevel(std::string filename)
{
pugi::xml_document doc; // engine pointer seems to be null here, what happened?
if (!doc.load_file(filename.c_str())) return 0;
pugi::xml_node map = doc.child("map");
for (pugi::xml_node n : map.children("tileset"))
{
std::string s = n.attribute("source").value();
std::cout << "Set: " << s << "\n";
int gid = n.attribute("firstgid").as_int();
TilesetHelper tsh;
tsh.gid = gid;
tsh.ts = engine->GetTilesetByName(s); // ACCESS VIOLATION - this is nullptr
tile_sets.push_back(tsh);
std::cout << s << " GID = " << gid << "\n";
}
|
All this code is called in Engine::LoadCFG
1 2 3 4 5 6 7 8 9 10 11
|
Engine::LoadCFG()
{
// ... Graphics
// ... Etc
pugi::xml_node map_config = config.child("Maps");
for (auto& cfg : map_config.children("entry"))
{
level_manager.Load(cfg.attribute("id").value(), cfg.attribute("filename").value()); // -
std::cout << cfg.attribute("filename").value() << " loaded\n";
}
}
|
Here's how the main is looking:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
#include "GameEngine.h"
#include "GameState.h"
#include "Menu.h"
//#include "PlayingState.h"
int main()
{
std::srand(unsigned int(std::time(0)));
try
{
GameEngine engine("Lands End");
//engine.Init();
engine.LoadCFG("Config\\config.xml"); // -
//engine.GetLevel("Test");
//MyState* menu = new MainMenu(&engine, engine.GetName());
//engine.AddState(menu,true);
//engine.AddState(new Overworld(&engine), false);
engine.Play();
return 0;
}
catch (std::string s)
{
std::cout << s << "\n";
std::cin.get();
}
catch (std::exception& e)
{
std::cout << e.what() << "\n";
}
}
|
Everything seemed to work fine before, to be honest I don't remember changing anything that may have caused this, but I've been hacking away for a couple days trying to get states to work so I might have done something without realising that I can't spot. Also please note my skills using a debugger are short of novice so take it with a grain of salt. :-) The engine pointer appears to be null on Level::Load but it seems to be assigned on Level constructor.
If anyone could help or you need all the code please let me know, I'm banging my head against the wall