Read access violation calling pointer function - "this is nullptr"

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
Last edited on
1
2
3
4
5
6
7
8
9
10
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));

        // *** does current_level have a valid, non-null value at this point?  
	current_level->LoadLevel(filename);

	current_level = levels[id]; // *** or should this line have been before the previous line?
}


Also, favour: levels[id] = std::make_shared<Level>(engine);
over levels[id] = std::shared_ptr<Level>(new Level(engine));
See: http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared
JLBorges... saved my ass once again. How the hell did I miss that? You were spot on, I must have dragged my mouse or someting.. 6 hours, 6 hours for that, trying to learn to use a debugger and everything. :-)

Everything compiling fine your a legend as usual, I owe you another beer. :-)

On a side I actually did have that make shared originally but trying to fix virtual functions and run I changed everything around, undoing everything I did. I've been putting off asking cause I knew it was something stupid.

Thanks again, you're the man.


EDIT: Hope you are doing well, been ages since I've visited the site, trying to refrain from asking unless I really have to, sad I broke my few months streak with such a silly error. :-)


EDIT 2: https://ibb.co/gUrMNn
Last edited on
Topic archived. No new replies allowed.