Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Object not null, but its contents are mangled?

Tags:

c++

I've been teaching myself C++ in VS2012 and have come across something that truly has gotten me scratching my head. When creating an object and adding a reference to it in another, the object seems to get corrupted or something. It's not null (every combination of null pointer check I could make confirms this), but its contents are funky and trying to access one of its members results in "0xC0000005: Access violation reading location 0xCCCCCCE8".

enter image description here

The gist of my program is that I have a 2D vector of Tile objects, each of which may have a reference to a Site. When I'm in a tile's draw() function that has a Site, it will attempt to draw that site in the colour that its civilisation belongs to.

World generation:

std::vector<std::vector<Tile>> world;
// ... vector is sized ...
// Populate world with tiles
for (int h=0; h<height; h++) {
    for (int w=0; w<width; w++) {
        Tile t(PLAINS);
        world[h][w] = t;
    }
}

When a civilisation is created, a simple capital site is created for them and a reference to it put in the tile at the specified x,y:

void Game::createCivilisation(std::string name, sf::Color colour, int x, int y) {

    // Create the civ
    Civilisation civ(name, colour);

    // Create their capital and link it up
    Site capital("Capital", year, &civ);  // when I comment these five lines out
    civ.capital = &capital;               // the program doesn't crash, so I know
    civ.sites.push_back(capital);         // that the dodgy site originates here.

    // Add capital to tile
    world[y][x].site = &capital;
    capital.location = &world[y][x];
}

By the time the Tile's draw() function is called however, it dies upon trying to access the site's members. This is with just the one civilisation.

if (site != nullptr) { // have also tried (site) (site!=0) (site!=NULL)
    sf::CircleShape s(tileWidth*0.5);
    s.setFillColor(site->civilisation->colour);  // womp womp

The image above is the debug info supplied. As you can see, it's all rubbish. "Capital" has become some billion-long string of garbage, everything is wrong, all the references to other objects are gone too. When I comment out the capital site linking

I think I've supplied all the relevant snippets of code (in the interest of brevity / for her pleasure). I've been working on this one for a few hours and it has me stumped. All indices should be correct, the site generated in createCivilisation() is definitely the only site in existence, etc...

like image 936
Tom Avatar asked Sep 22 '13 07:09

Tom


2 Answers

This is wrong

Site capital("Capital", year, &civ);  // when I comment these three lines out
civ.capital = &capital;               // the program doesn't crash, so I know
civ.sites.push_back(capital);         // that the dodgy site originates here.

// Add capital to tile
world[y][x].site = &capital;

You are storing a pointer &capital to a local object (and doing it twice it seems). When your createCivilisation method exits that local object is destroyed and so you end up with pointers to garbage.

The simple answer is for you to copy the object itself instead of trying to store a pointer. If the objects are large and therefore copying them is an issue, you should look to dynamic heap allocation and smart pointers.

like image 154
john Avatar answered Sep 30 '22 01:09

john


When running in debug mode, Visual Studio automatically fills freed (or out-of-scope) memory with 0xCCCCCCCC. This enables you to catch use-after-free bugs, like the one you just encountered.

You are creating a reference to a local variable (stack variable). The variable goes out of scope at the conclusion of the method, leaving a dangling pointer in world.

You may wish to allocate the objects on the heap instead:

Site *capital = new Site("Capital", year, &civ);

though you must figure out when to free capital to avoid memory leaks. You can also use smart pointers (in this case a shared_ptr or similar) to simplify your life.

like image 32
nneonneo Avatar answered Sep 30 '22 02:09

nneonneo