Strange Error with Vectors in C++ - c++

Every time I compile the code for a RTS Project I am working on, I get this error:
error C2664: 'std::_Vector_iterator<_Ty,_Alloc> std::vector<_Ty>::erase(std::_Vector_const_iterator<_Ty,_Alloc>)' : cannot convert parameter 1 from 'MAPTILE *' to 'std::_Vector_const_iterator<_Ty,_Alloc>'
The code area that I have for this method is this:
MAPTILE *startTile = GetTile(start);
MAPTILE *goalTile = GetTile(goal);
...
std::vector<MAPTILE*> open; //Create Our Open list
startTile->g = 0; //Init our starting point (SP)
startTile->f = H(start, goal);
startTile->open = true;
open.push_back(startTile); //Add SP to the Open list
bool found = false; // Search as long as a path hasnt been found,
while(!found && !open.empty()) // or there is no more tiles to search
{
MAPTILE * best = open[0]; // Find the best tile (i.e. the lowest F value)
int bestPlace = 0;
for(int i=1;i<open.size();i++)
if(open[i]->f < best->f)
{
best = open[i];
bestPlace = i;
}
if(best == NULL)break; //No path found
open[bestPlace]->open = false;
open.erase(&open[bestPlace]); // Take the best node out of the Open list
I have searched on this website and a few others, but I could not find the correct area.
I am reading "Programming a RTS Game With Direct3D" By Carl Granberg.
All of my code is right because I matched it with the source code, and I got the same error.
I am using Visual C++ 2008 Express Edition.
I have never gotten this error before.

erase wants an iterator and you are giving it a pointer to an element within the array. Use std::advance or keep a handle to an iterator.
std::vector<MAPTILE*> p = open.begin();
std::advance(p, bestPlace);
open.erase(p);
EDIT I forgot that std::advance doesn't return anything. Sorry about that. I haven't done serious C++ development for about five years.
I would rewrite your for loop to use iterators instead of indexes.
I believe that the following snippet is equivalent to your snippet after replacing the array indexing with iterators. I had to add the typedef to make it more readable.
MAPTILE *startTile = GetTile(0);
startTile->g = 0;
startTile->f = H(0, 10);
startTile->open = true;
std::vector<MAPTILE*> open;
open.push_back(startTile);
typedef std::vector<MAPTILE*>::iterator Iterator;
bool found = false;
while (!found && !open.empty()) {
Iterator best = open.begin();
for (Iterator iter=best+1, end=open.end();
iter!=end; ++iter)
{
if ((*iter)->f < (*best)->f) {
best = iter;
}
}
if (*best == NULL) {
break;
}
(*best)->open = false;
open.erase(best);
}
I'm not completely convinced that the if (*best == NULL) condition will ever be matched though. This compiles without error under clang++ (sorry, no visual studio in my house). When I run your snippet through clang++, I get comparable failures to yours:
foo.cpp:85:14: error: calling a private constructor of class
'std::__1::__wrap_iter<MAPTILE *const *>'
open.erase(&open[bestPlace]);
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/iterator:1381:31: note:
declared private here
_LIBCPP_INLINE_VISIBILITY __wrap_iter(iterator_type __x) _NOEXCEPT_D...
^
1 error generated.
I don't know what else to say, std::vector<>::erase takes a std::vector<>::iterator parameter and that's all that there is to it. My guess is that the book was written against a version of VC++ that used pointers for vector iterators though I don't recall one that ever did that.

Related

Values of the function parameters are changing randomly (but they're not modified from the code)

I have to implement an NBC (for finding clusters in the provided set of data) algorithm at my class project with a friend. We came across very strange issue. There are few helper functions, and the one with a problem is kNN (possibly kEN too) in the kNB.h file. After passing arguments to it from the main function of the program (for example k=3 and p=5), it goes to the kNN function and starts changing values of k and p randomly, even though function code is not supposed to do that anywhere as you can see below.
Also, while using debugging mode and going through this function step by step I noticed that it sometimes comes back before the first while which I think shouldn't happen. I guess it may be some trivial mistake, but I'm not very good at C++ (unfortunately we were ordered to use it). You can download entire Visual Studio 2013 solution from here: https://dl.dropboxusercontent.com/u/1561186/EDAMI.zip. So, does anyone have any idea why described situation is happening?
static vector<int> kNN(int k, int p, Dataset<V>* records)
{
int b = p, f = p;
bool backwardSearch, forwardSearch;
vector<int> tmp;
LengthMetric<V>* lengthMetric = records->getLengthMetric();
backwardSearch = PrecedingPoint(records, b);
forwardSearch = FollowingPoint(records, f);
int i = 0;
while (backwardSearch && forwardSearch && i < k)
{
if (records->getRecord(p)->getLength() - records->getRecord(b)->getLength() < records->getRecord(f)->getLength() - records->getRecord(p)->getLength())
{
i++;
tmp.push_back(b);
backwardSearch = PrecedingPoint(records, b);
}
else
{
i++;
tmp.push_back(f);
forwardSearch = FollowingPoint(records, f);
}
}
while (backwardSearch && i < k)
{
i++;
tmp.push_back(b);
backwardSearch = PrecedingPoint(records, b);
}
while (forwardSearch && i < k)
{
i++;
tmp.push_back(f);
forwardSearch = FollowingPoint(records, f);
}
return tmp;
}
Look at second constructor of your class Dataset
Dataset(vector<Record<V>*> rrecords,
LengthMetric<V>* metric = new DumbLengthMetric<V>())
: records(rrecords),
lengthMetric(lengthMetric) { // <-------------------
lengthMetric(lengthMetric) does nothing. Changing it to lengthMetric(metric) I got some result on your project and no one variable was changed.
BTW, do not include in zip any stuff like folders Debug, Release and files *.sdf, *.ncb

Trouble removing elements from C++ vector

I'm trying to remove 'dead' bullets from my vector of bullets. Every frame, I'm calling the Bullet::update() function which looks like this:
void Bullet::update()
{
for(int i = 0; i != mAmmo.size(); i++)
{
if(mAmmo[i].sprite.getPosition().x > 700)
mAmmo[i].mAlive = false;
if(mAmmo[i].mAlive == false)
{
// I get a Debug Assertion Failed at runtime from this piece of code
mAmmo.erase(mAmmo.begin()+i);
}
if(mAmmo[i].mAlive == true)
{
mAmmo[i].sprite.move(mMovement);
}
}
}
Am I doing this completely incorrectly? This is the first time I've really used vectors more than just following through a tutorial. If I need to post any more code, just tell me. I've been working on this for the past few hours, so I'm a wee bit desperate to get this to work.
Thanks in advance!
You're easily walking into undefined behavior as soon as the ith element is the last element in your list. Use iterators, and pay special attention to the return value of erase(), as it automatically advances the iterator for you so your loop doesn't have to.
void Bullet::update()
{
for (auto it = mAmmo.begin(); it != mAmmo.end();)
{
if(it->sprite.getPosition().x > 700)
it->mAlive = false;
if (!it->mAlive)
{
// erase and get next iterator
it = mAmmo.erase(it);
}
else
{ // move and increment
it->sprite.move(mMovement);
++it;
}
}
}

Valgrind detects invalid read error in simple Iterator class

Valgrind detects an invalid read error I don't know how to fix or to be more precise: I don't know what the problem is.
Invalid read of size 8
at 0x443212: std::vector<Tile*, std::allocator<Tile*> >::end() const
by 0x44296C: Collection<Tile*>::Iterator::operator++()
The Iterator class is very simple (and actually a somewhat bad piece of programming) but sufficient for my needs right now. I think there are three methods you should know to hopefully help find my problem:
Iterator(size_t x, size_t y, const TileCollection& tiles)
: mTiles(&tiles)
, mX(mTiles->begin())
, mY(mTiles->at(x).begin())
{
std::advance(mX, x);
std::advance(mY, y);
bool foundFirst = false;
while (!foundFirst)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundFirst = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
}
Iterator Iterator::operator++()
{
bool foundNext = false;
++mY;
while (!foundNext)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundNext = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
return *this;
}
void TileCollection::add(Tile* tile)
{
Point2D p(tile->getPosition());
std::vector<Tile*> tmp(1, (Tile*)0);
if ((size_t)p.x >= mTiles.size())
mTiles.resize(p.x + 1, tmp);
if ((size_t)p.y >= mTiles.at(p.x).size())
mTiles.at(p.x).resize(p.y + 1, (Tile*)0);
mTiles.at(p.x).at(p.y) = tile;
++mNumTiles;
}
The actual code that is causing the valgrind error is the line:
while (mY != mX->end() && *mY == 0) ++mY;
...of the Iterator::operator++ method.
It looks to me that, at the least, the following line in operator++
if (mX != mTiles->end()) mY = mX->begin();
is lacking a suitable else-clause.
Consider what happens when mX actually reaches mTiles->end(): You will enter a new iteration of the outer while loop; the first line in that loop (the line that causes the Valgrind error) will evaluate mX->end() and thus attempt to dereference mX -- but mX is mTiles->end(), and it's not correct to dereference the end iterator of a collection since it doesn't actually reference an element of the collection. It looks to me as if this may be the cause of your Valgrind error.
(Note that the constructor contains essentially the same code.)
More generally, I think you need to think about how you handle reaching the end of your two-dimensional array. How does the client of your Iterator check whether it has reached the end of the iteration? How do you expect your operator++ to handle the case when it reaches the end of the two-dimensional array? Should it protect itself against getting called too often?
You can try to split up the statement in order get find out where the error occurs:
while (mY != mX->end()) // maybe here
{
if (*mY != 0) // maybe here
{
break;
}
++mY; // maybe here
}
Compiling with GCC compiler option -fno-inline helps to get a nicer stack-trace, which can help you to trace the error. It will also make your program very slow, so don't forget to remove it later.

Using push_back() for STL List in C++ causes Access Violation, Crash

I'm creating a game using my own homemade gaming engine, but I'm running into trouble using lists.
I have a structure in my program called BoardState. Each of these structures has a list of BoardState pointers called children. This is because I create a tree of BoardStates for the AI of my game.
To aid in the creation of my tree, I have a function called MakeBoard. This function gets passed all the information it needs to create a new board, and then it should add the pointer to that new board to the end of the parent board's children list. Here is the relevant function, MakeBoard:
void MakeBoard(BoardState* pStartBoard, int iPiece, int iPosStart, int iPosFinish, int* pJumpArray)
{
//BoardState* pNewBoard = &NewBoard;
//pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
//NewBoard.bPlayerTurn = !(pStartBoard->bPlayerTurn);
BoardState* pNewBoard = (BoardState*)malloc(sizeof(BoardState));
pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
// Copy the BoardPositions of the starting board into the new Board.
for(int i = 0; i < 37; i++)
{
pNewBoard->posArray[i] = pStartBoard->posArray[i];
//NewBoard.posArray[i] = pStartBoard->posArray[i];
}
// Make the BoardPosition change necessary to reflect the move.
pNewBoard->posArray[iPosStart] = -1;
pNewBoard->posArray[iPosFinish] = iPiece;
//NewBoard.posArray[iPosStart] = -1;
//NewBoard.posArray[iPosFinish] = iPiece;
// Now account for any pieces that were jumped, if applicable.
if(pJumpArray != NULL)
{
for(int i = 0; i < 16; i++)
{
if(pJumpArray[i] != -1)
{
pNewBoard->posArray[pJumpArray[i]] = -1;
//NewBoard.posArray[pJumpArray[i]] = -1;
}
}
}
// Connect the parent board to this child board.
pNewBoard->parent = pStartBoard;
//NewBoard.parent = pStartBoard;
//pStartBoard->children.push_back(_pTestState);
pStartBoard->children.push_back(pNewBoard); // <- The problem
//pStartBoard->children.push_back(&NewBoard);
}
The extra commented parts are where I was trying out other ideas to see if they worked.
Unfortunately this causes the program to throw the following error:
Access violation reading location 0xcdcdcdd1.
If I dig into the debugger, I find out that the problem is occurring in the STL list file. These are the top three calls in the call stack:
OpenGL_Engine_Test1.exe!std::list >::_Insert(std::list >::_Const_iterator<1> _Where=..., tagBoardState * const & _Val=0x049a1a80) Line 718 + 0x10 bytes C++
OpenGL_Engine_Test1.exe!std::list<tagBoardState *,std::allocator<tagBoardState *> >::push_back(tagBoardState * const & _Val=0x049a1a80) Line 670 + 0x51 bytes C++
OpenGL_Engine_Test1.exe!MakeBoard(tagBoardState * pStartBoard=0x049a0580, int iPiece=16, int iPosStart=21, int iPosFinish=16, int * pJumpArray=0x00000000) Line 352 C++
It then opens up the file where list is defined, and points out the problem line inside the _insert function:
void _Insert(const_iterator _Where,
const _Ty& _Val)
{ // insert _Val at _Where
#if _HAS_ITERATOR_DEBUGGING
if (_Where._Mycont != this)
_DEBUG_ERROR("list insert iterator outside range");
#endif /* _HAS_ITERATOR_DEBUGGING */
_Nodeptr _Pnode = _Where._Mynode();
_Nodeptr _Newnode = _Buynode(_Pnode, _Prevnode(_Pnode), _Val); // PROBLEM
_Incsize(1);
_Prevnode(_Pnode) = _Newnode;
_Nextnode(_Prevnode(_Newnode)) = _Newnode;
}
Beyond this, i don't really know more. I have no idea why this problem is occurring. I know that an "Access Violation" basically means that I'm either trying to access something that doesn't exist, I don't have access to, or there is some sort of scope problem, but I can't see how any of those are applicable.
If anyone can point me in the right direction, I would really appreciate it. I've done a lot of searching, but almost everything I've found has been pertaining to Vectors and haven't seemed to be my issue exactly.
If you malloc() a C++ class, no constructors will be called for any of that class's fields, including your problem vector. You need to use new.
I've made an assumption that pStartBoard was allocated the same as pNewBoard, but you will have the same problem in pNewBoard even if this is not the case.
Access violation reading location 0xcdcdcdd1. Indicates an unitialized variable. The debugger puts in values like that as markers. Unfortunately, I can't deduce where you are seeing the error, nor any STL containers in your code sample. But 'pNewBoard->posArray' would be the first place I look. Does that class's constructor set that member to something?

What's wrong with my recursive function?

So I'm trying to implement a recursive function that generates the entire game tree of Tic-Tac-Toe, and I can't seem to get it to work.
void BuildTree(Node& nNode, const int& nextPlayer)
{
//Copy last board
Ticboard tBoard = nNode.m_board;
do
{
//Return first valid move
int validMove = tBoard.FirstValidMove();
if (validMove != -1)
{
Node f;
Ticboard tempBoard = nNode.m_board;
tempBoard.Move(validMove, nextPlayer);
tBoard.Move(validMove, nextPlayer);
f.m_board = tempBoard;
f.m_winCount = 0;
nNode.m_branches.push_back(f);
int currPlay = (nextPlayer == 1 ? 2 : 1);
BuildTree(f,currPlay);
}
else
{
break;
}
}while(true);
}
The actual function works, I've gone through and debugged it and it SHOWS it working as it is supposed to, but when I look at the nodes generated (for Tic-Tac-Toe, by the way) in Visual Studios via breakpoint, it only shows the first 9 branches. I know more were generated because it takes a few seconds, and I added a counter.
Here's how I call the code:
Ticboard lol;
Node startTree;
startTree.m_board = lol;
int startPlay = 1;
BuildTree(startTree, startPlay);
Without copying all my code for bitboards and whatnot in here, can you see anything immediately wrong with the logic?
nNode.m_branches.push_back(f);
This will push_back a copy of the Node f, so the stuff inside nNode.m_branches will be irrelevant to the modification of f later on.