Advertisement

Crash with <unable to read memory> error

Started by December 01, 2014 02:52 AM
8 comments, last by BitMaster 10 years, 1 month ago

I don't know how to fix this error that popped up when I tried to assign value of variable to another variable. Program crashes when I try to assign value of variable B to variable A, this thing should not happen, and I think I already tried everything. This is what I have:


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

	int SetMapSizeX(int SizeX);
	int SetMapSizeY(int SizeY);

	int GetMapSizeX();
	int GetMapSizeY();
	int GetMapSize();

	int MapSizeX;
	int MapSizeY;
	int MapTotalSize;
};

GameMap::GameMap()
{
	MapSizeX = 0;
	MapSizeY = 0;
	MapTotalSize = 0;
}

GameMap::~GameMap()
{
}

int GameMap::SetMapSizeX(int SizeX)
{
	return MapSizeX = SizeX;
}

int GameMap::SetMapSizeY(int SizeY)
{
	return MapSizeY = SizeY;
}

int GameMap::GetMapSizeX()
{
	return  MapSizeX;
}

int GameMap::GetMapSizeY()
{
	return MapSizeY;
}

int GameMap::GetMapSize()
{
	GetMapSizeX();
	GetMapSizeY();

	return MapTotalSize = MapSizeX + MapSizeY;
}

Code maybe looks bad but it, had to separate everything so I can findout what exactly caused this error.

So, the crash is on this line:


return MapSizeX = SizeX;

I am not sure what am I doing wrong here.

Check the object you're calling on; it could be null or invalid.
Advertisement

Ok i fixed it, thank you. Turns out I can't access with -> instead I need to use (dot).

my code had the following:


GameMap* Map;
Map->CreateMap(5, 5);

... and a like.

now it MUST be


GameMap Map;
Map.CreateMap(5, 5);

Why is this?

Because your code just results in a pointer to something which is invalid (you haven't created an instance yet). It hasn't been set to anything, and you try to access it.

You should be able to do this:

GameMap *Map = new GameMap;
Map->CreateMap(5, 5);

Remember to delete the Map instance when it's no longer needed, to avoid leaking memory.

Hello to all my stalkers.

It crashes because dereferencing an uninitialized variable is undefined behaviour.

Lesson number 1 learned.

Stephen M. Webb
Professional Free Software Developer

The key idea is that pointers must point to something. It is safest to try ensure every pointer is immediately initialised to a valid address or "nullptr". In fact, that advice is best followed for variables of any sort.

Another alternative:

GameMap map;
// Later, perhaps via a function parameter
GameMap *pointer = &map;
pointer ->CreateMap(5, 5);

Note that you do not have to delete this pointer, as it is pointing at an existing value, but you do have to be careful not to use pointers to a value once they go out of scope:

GameMap *badMap()
{
    GameMap value;
    return &value; // When this function returns, the "GameMap" object above is destroyed!
}
 
int main()
{
    GameMap *pointer = badMap();
    // Oh no, the value in "badMap" no longer exists, so this is undefined behaviour!
    pointer->CreateMap(5, 5);
}

Note that undefined behaviour can exhibit a wide variety of behaviours, including appearing to work! It can also explode immediately, or corrupt variables elsewhere in the program. The behaviour can change from run to run, making this can be incredibly difficult to understand and fix. Best to try and catch it early, by being proactive and disciplined in initialising variables, among other things.

Advertisement
std::unique_ptr<GameMap> Map = std::make_unique<GameMap>();
Map->CreateMap(5, 5);
It's almost 2015. Let's start teaching novice users to do things right instead of perpetrating fragile C/C++98-isms.

Sean Middleditch – Game Systems Engineer – Join my team!


std::unique_ptr<GameMap> Map = std::make_unique<GameMap>();
Map->CreateMap(5, 5);
It's almost 2015. Let's start teaching novice users to do things right instead of perpetrating fragile C/C++98-isms.

Not everyone has a C++14 compliant compiler (which is required for std::make_unique<>()), the standard was only ratified this last August. Heck, plenty of folks are still stuck with a 1997-vintage compiler.

That said, if you have a C++14 compiler, that's a good way to do pointers once you understand them and the implications of ownership transfer and move vs. copy.

Stephen M. Webb
Professional Free Software Developer

std::unique_ptr<GameMap> Map = std::make_unique<GameMap>();
Map->CreateMap(5, 5);
It's almost 2015. Let's start teaching novice users to do things right instead of perpetrating fragile C/C++98-isms.

I almost feel like you're implying using bare pointers is outdated, which is silly, a beginner looking at that code would be just as clueless about what it is doing as they would be about a bare pointer and understanding new vs delete.

Smart pointers are a tool, a tool best used when you understand when they will go out of scope and destroy their contents just as much as it is important to understand that using bare pointers is fine if you need to control their destruction more specifically.

A more pragmatic thing to do would have been to suggest that as an alternative and why.
Back in the days when Zahlman was the 'For Beginners' moderator he had a signature that said (paraphrased) "If you post in For Beginners and your code contains 'char*', you have a bug". I'd say nowadays that can be extended to any raw pointer.

I would not say raw pointers are outdated but between std::shared_ptr, std::unique_ptr and boost::intrusive_ptr I would be very hard pressed to find an active reason to use raw pointers with any kind of lifetime management. In cases where some kind of resource management does not fit into the established pattern I would strongly suggest writing a compact RAII wrapper which deals with that exact problem.

The only time raw pointers with any kind of lifetime management matter to me in my professional life nowadays is when I descend into the abyss (that is, the code written a decade or more ago by people who thought C++ meant C with a tiny bit of classes).

My current hobby project uses raw pointers but not in any way regarding lifetime management.

This topic is closed to new replies.

Advertisement