std::vector .begin() throwing error

Dec 19, 2014 at 8:51am
Hi guys, I have been trying to use the .begin() function of a std::vector inside a class, but it throws an error. I have been using the exact same line of code inside other member functions of my class without any problems. It throws an error as soon as I call .begin() or .end(). The script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool AlienManager::CollisionCheck(sf::FloatRect blastradius)
{
	bool _intersects = false;
	std::vector<Object_Alien>::iterator itr = _objects.begin();
	while (itr != _objects.end())
	{
		bool temp = blastradius.intersects(itr->GetGlobalBounds());
		if (temp)
		{
			itr = Remove(itr);
			_intersects = true;
		}
		else
			itr++;
	}
	return _intersects;
}


The _object variable is of std::vector<Object_Alien> type, and it is only in this function where it throws this error. _objects is never deleted so I have no idea why it is throwing the error. Also I thought .begin() had a no-throw guarantee. The error I'm receiving from VS is as follows:

Unhandled exception at 0x00a544f4 in Space Invaders.exe: 0xC0000005: Access violation reading location 0xcdcdcdd5.


Is there anything else I can try? Thanks for any help in advance!

EDIT: Also I should mention I tried swapping out std::vector for std::list yet I get the same error
Last edited on Dec 19, 2014 at 8:53am
Dec 19, 2014 at 9:22am
I might be wrong, but as I remember iterators should be used like:
(*itr)->

Why do you use "Remove" instead with "_objects.erase(itr);"?

Are you multi-threading?

Also, don't do "_..." names, they can cause name clashes, do "..._".
Dec 19, 2014 at 9:26am
This code seems ok to me, maybe something is going wrong in your Remove function?
Dec 19, 2014 at 9:36am
The iterator is used correctly in this case, (*itr)-> is useful when you have a array of pointers ;)

Unless of course Object_Alien is a typedef of a pointer type.
Dec 19, 2014 at 9:47am
Thanks for the quick replies!

@poteto The std::vector contains the classes themselves, not pointers to them because I read somewhere that to store raw pointers in containers is a bad idea (please correct me on this if I'm wrong). Also I read that calling .erase() doesn't call the destructor of the class contained in the vector, so Remove() first deletes the class then I'm using .erase() to remove the objects from the vector.

@BasV I also thought so but from previous testing the Remove() function seems to be working fine. The classes contained in the vector are allocated with the new function, so the Remove function is as follows:

1
2
3
4
5
6
std::vector<Object_Alien>::iterator AlienManager::Remove(std::vector<Object_Alien>::iterator itr)
{
	_currentScore += itr->GetScore();
	delete &itr;
	return _objects.erase(itr);
}


I just thought about this, is the Remove function already deleting the objects from the vector before using .erase()?

EDIT: Ok I reverted back to to the vector storing the pointers to the classes, so the remove function is now the following:

1
2
3
4
5
6
std::vector<Object_Alien*>::iterator AlienManager::Remove(std::vector<Object_Alien*>::iterator itr)
{
	_currentScore += (*itr)->GetScore();
	delete (*itr);
	return _objects.erase(itr);
}
Last edited on Dec 19, 2014 at 9:55am
Dec 19, 2014 at 9:56am
You shouldn't delete &itr. First of all, you're deleting a pointer to the iterator, and you never allocated that yourself.

Secondly, if you want to delete your old object, you probably don't need to. If it's not a pointer, erase will do everything for you. Unless you have a specific function that does cleaning up, you can call that now.

If you never allocated your Object_Alien, you don't need to delete it.

I presume you initialize your Object_Aliens by doing something like:

1
2
3
Object_Alien ob;

_objects.push_back(ob);


In that case, just calling

_objects.erase(itr);
is fine!


edit: I overlooked you saying that they are allocated with the new statement. When you place such objects in a vector, a copy is made. So your original allocated data is now lost and you can't delete that anymore. You need to store the pointers in an array, and delete those:

std::vector<Object_Alien*> _objects;

Last edited on Dec 19, 2014 at 10:00am
Dec 19, 2014 at 10:22am
> Unhandled exception: Access violation reading location 0xcdcdcdd5.
> Also I thought .begin() had a no-throw guarantee.
I'll concede that the message can be confusing.
The problem is not a throw that is not being catch, the problem is trying to read memory that you don't own. (in your case seems to be produced by those bad deletes)

The trhow case (like in .at() ) would be something like
gdb wrote:
terminate called after throwing an instance of '...'
Program received signal SIGABRT, Aborted.



> You need to store the pointers in an array, and delete those:
Better yet, store intelligent pointers so you don't need to delete those.
As a rule, if you have to write delete you are probably doing something wrong
Dec 19, 2014 at 5:01pm
Ok I tried avoiding using delete so I rewrote the code so that I simply declare a class without using new and then add it to the _objects, but I noticed something. Object_Alien is merely a superclass, all the classes I add to _objects are all derived classes of Object_Alien, and although I declared the main functions needed in the derived classes as virtual, it still calls the functions defined in Object_Alien, not the derived class. How can I fix this? Thanks for all the help so far!
Dec 19, 2014 at 5:10pm
You have a slicing problem. After you shore Child object in container of Parents, the object stored will be of class Parent! All additional info will be lost.

In this case you need container of [smart]pointers, or references (reference_wrappers to be precise, as you cannot store references in containers directly)
Dec 20, 2014 at 5:54am
@MiiniPaa Thank you for the explanation, first time getting into OOP :)

After tedious debugging I found the error... I forgot to initialize the _alienManager variable... Thank you for the help guys, happy holidays!
Topic archived. No new replies allowed.