Cleaning up a vector of pointers?

Started by
26 comments, last by Storyyeller 11 years, 11 months ago
Hey everybody. I've run into a snag, and I can't quite figure it out. I'm making a maze game with c++ and SFML.

My problem is with my Map class. My map class parses a text file (which is a text version of the map grid), and reads all 1s as Walls and all 0s as blank spaces. The 0s are ignored, and for each 1 that it encounters, it takes the coordinates of the '1' and creates a pointer to a Wall object with those coordinates, and adds it to my _mazeMap vector.


vector _mazeMap;

_mazeMap.push_back(new Wall(x, y));


is the gist of it.

My problem is cleaning up the memory. In my Map class' destructor I figure I need to delete all the pointers that were created in the vector, correct? So this is the code I wrote to try and do it:


Map::~Map()
{
    std::vector::iterator iter = _mazeMap.begin();
    
    for (iter = _mazeMap.begin(); iter != _mazeMap.end(); ++iter)
    {
        delete *iter;
    }
}


However, every time I run the game, when I shut it down, and the Destructor gets run, I get this error:

Thread 1: Program received signal: "EXC_BAD_ACCESS"

I have no idea what I'm doing wrong. Any help? Thanks so much.
Advertisement
What line is it actually crashing at?
Unless one of these pointers already got deleted somewhere else, there is nothing wrong with your loop.
However, it is always a good idea to also empty the vector when you are done... but this shouldn't be a problem here.


Map::~Map()
{
std::vector::iterator iter = _mazeMap.begin();

for (iter = _mazeMap.begin(); iter != _mazeMap.end(); ++iter)
{
delete *iter;
}
_mazeMap.clear();
}
You have confirmed that commenting out only the 'delete *iter;' line removes the crash?

In that case, I suspect you are either doing double delete, or the 'this' pointer in Map dtor is bad to start with. Check that you don't make value copies of the Map object, or that if you do, you have proper copy-ctor and assignment operators defined, since otherwise making copies of _mazeMap containers will cause duplicates of the pointers to be created, leading to a double delete on the long run.
It gives me the bad access error on the
delete *iter
line.


I'm still not sure what's wrong. It's still happening, and I can't really understand it.
Here's my code that Loads the Map/Vector in case that would help at all.



// Loads the map from a text file.
void Map::Load()
{

// Opens the file.
std::ifstream loadedFile;
loadedFile.open("images/level.txt");

// Variable that will hold each line for parsing.
std::string line;

// Counts how many rows have been completed.
int rowcounter = 0;

// Makes sure the file has opened.
if(loadedFile.is_open())
{
// Remains true until the file has ended.
// Loops through each line.
while(std::getline(loadedFile, line))
{
// Once the line has been put into the string variable,
// this will go through each character an check for walls.
for (int i = 0; i < LEVELWIDTH; i++) {

// If a wall (a '1' character in the text file) is found
// then this will put it into the vector.
if (line == '1') {
_mazeMap.push_back(new Wall(i, rowcounter));
}
}
// After the line has been parsed, this iterates the counter.
rowcounter++;
}
}
}



Edit:

Yes, commenting out the (delete *iter) line causes the bug to disappear.
As far as I'm aware, I don't make any copies of _mazeMap or Map objects. I have a single static Map object in my Game Global, and that's it.
What is your wall destructor?

What is your wall destructor?


It's empty. Is that where my problem lies? I didn't give it much thought since it just has a few member variables and a draw function.
Can you print out 'printf("0x%p", *iter);' just before calling 'delete *iter;' to confirm that double-delete doesn't occur?

Also, going for more exotic causes, can you check that you use the matching implementations of operator new and delete, and e.g. don't straddle the calls across module boundaries, or don't have any custom (debug-mode?) new/delete implementations going on.

Can you print out 'printf("0x%p", *iter);' just before calling 'delete *iter;' to confirm that double-delete doesn't occur?

Also, going for more exotic causes, can you check that you use the matching implementations of operator new and delete, and e.g. don't straddle the calls across module boundaries, or don't have any custom (debug-mode?) new/delete implementations going on.


This is the output I get when that printf statement executes: 0x0xc00000001012f520
And that's all I get. I'm not extremely experienced at programming, just enough to know what I'm doing, I'd say. However, I'm not sure how to go about checking my implementations of new and delete. I haven't overloaded them, if that's what you're asking? How should I go about checking what implementations of new and delete I'm using? Thanks for the help.

Edit:
I commented out the (delete *iter) line with the printf statement still inserted. It gave me a ton of memory addresses. So, for some reason the program is crashing as soon as it tries to delete the first pointer.
Instead of "delete *iter; ", try this:
if (*iter) {delete *iter; *iter = NULL;}

Does the crash go away? If so you've definitely got double-delete, if not then you've got something a little more insidious.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


Instead of "delete *iter; ", try this:
if (*iter) {delete *iter; *iter = NULL;}

Does the crash go away? If so you've definitely got double-delete, if not then you've got something a little more insidious.


The crash did not go away when I replaced the code.

Here's my debugger output if that sheds light on anything? I'm just lost. I can't figure out what I'm doing wrong.



GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Thu Nov 3 21:59:02 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys000
warning: Unable to read symbols for @executable_path/../Frameworks/sfml-audio.framework/Versions/A/sfml-audio (file not found).
warning: Unable to read symbols from "sfml-audio" (not yet mapped into memory).
warning: Unable to read symbols for @executable_path/../Frameworks/sfml-graphics.framework/Versions/A/sfml-graphics (file not found).
warning: Unable to read symbols from "sfml-graphics" (not yet mapped into memory).
warning: Unable to read symbols for @executable_path/../Frameworks/sfml-network.framework/Versions/A/sfml-network (file not found).
warning: Unable to read symbols from "sfml-network" (not yet mapped into memory).
warning: Unable to read symbols for @executable_path/../Frameworks/sfml-system.framework/Versions/A/sfml-system (file not found).
warning: Unable to read symbols from "sfml-system" (not yet mapped into memory).
warning: Unable to read symbols for @executable_path/../Frameworks/sfml-window.framework/Versions/A/sfml-window (file not found).
warning: Unable to read symbols from "sfml-window" (not yet mapped into memory).
warning: Unable to read symbols for @executable_path/../Frameworks/SFML.framework/Versions/A/SFML (file not found).
warning: Unable to read symbols from "SFML" (not yet mapped into memory).
[Switching to process 49627 thread 0x0]
0x0x1000000000000000sharedlibrary apply-load-rules all
Warning: the current language does not match this frame.
Current language: auto; currently c++
(gdb)


Update: Does this help at all? It's a picture of my debug area, and I think it's showing what's going on underneath the iterator. I'm not sure I particularly understand it though.
2ppelnb.jpg

Update 2:
Could my issue have anything to do with the fact that class Wall extends VisibleGameObject? I have a blank virtual destructor in VisibleGameObject and a blank destructor in Wall.

This topic is closed to new replies.

Advertisement