Bad access on reading vector iterator - c++

I have a vector<int> called pitches. I'm getting periodic bad access on the last line below:
int play = 0;
bool didFind = 0;
vector<int>::const_iterator iterator;
for (iterator = pitches.begin(); iterator != pitches.end(); ++iterator) {
if (*iterator > lastpitch) { // lastpitch is an int
didFind = 1;
play = *iterator;
break;
}
}
if (!didFind) play = *(pitches.begin()); // this line gives me bad access
I had previously tried *pitches.begin() on the last line but that always provided bad access and I understand that now. But while I get it less often now, this play=*(pitches.begin()); is still doing the same occasionally. I cannot see anything in the above that would cause that, any suggestions appreciated.

If pitches vector has size 0, the things inside
for (iterator=pitches.begin();iterator!=pitches.end();++iterator)
doesn't get executed and therefore didFind=0.
The statement inside if is evaluated. Yet pitches is empty means pitches.begin()==pitches.end(). Dereferencing a pitches.end() is to access out of bound and therefore gives bad access.

Related

Removing first three elements of 2d array C++

So here's my problem.. I have a 2d array of 2 char strings.
9D 5C 6S 9D KS 4S 9D
9S
If 3 found I need to delete the first 3 based on the first char.
card
My problem is I segfault almost anything i do...
pool is the 2d vector
selection = "9S";
while(col != GameBoard::pool.size() ){
while(GameBoard::pool[col][0].at(0) == selection.at(0) || cardsRem!=0){
if(GameBoard::pool[col].size() == 1){
GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
}
else{
GameBoard::pool[col].pop_back();
cardsRem--;
}
}
if(GameBoard::pool[col][0].at(0) != selection.at(0)){
col++;
}
}
I've tried a series of for loops etc, and no luck! Any thoughts would save my sanity!
So I've tried to pull out a code segment to replicate it. But I can't...
If I run my whole program in a loop it will eventually throw a segfault. If I run that exact code in the same circumstance it doesn't... I'm trying to figure out what I'm missing. I'll get back in if I figure out exactly where my issue is..
So in the end the issue is not my code itself, i've got memory leaks or something somewhere that are adding up to eventually crash my program... That tends to be in the same method each time I guess.
The safer and most efficient way to erase some elements from a container is to apply the erase-remove idiom.
For instance, your snippet can be rewritten as the following (which is testable here):
using card_t = std::string;
std::vector<std::vector<card_t>> decks = {
{"9D", "5C", "6S", "9D", "KS", "4S", "9D"},
{"9S"}
};
card_t selection{"9S"};
// Predicate specifing which cards should be removed
auto has_same_rank = [rank = selection.at(0)] (card_t const& card) {
return card.at(0) == rank;
};
auto & deck = decks.at(0);
// 'std::remove_if' removes all the elements satisfying the predicate from the range
// by moving the elements that are not to be removed at the beginning of the range
// and returns a past-the-end iterator for the new end of the range.
// 'std::vector::erase' removes from the vector the elements from the iterator
// returned by 'std::remove_if' up to the end iterator. Note that it invalidates
// iterators and references at or after the point of the erase, including the
// end() iterator (it's the most common cause of errors in code like OP's).
deck.erase(std::remove_if(deck.begin(), deck.end(), has_same_rank),
deck.end());
So for anyone else in the future who comes across this...
The problem is I was deleting an element in the array in a loop, with the conditional stop was it's size. The size is set before hand, and while it was accounted for in the code it still left open the possibility for while(array.size() ) which would be locked in at 8 in the loop be treated as 6 in the code.
The solution was to save the location in the vector to delete and then delete them outside of the loop. I imagine there is a better, more technical answer to this, but it works as intended now!
for (double col = 0; col < size; ++col)
{
if(GameBoard::pool[col][0].at(0) == selection.at(0)){
while(GameBoard::pool[col][0].at(0) == selection.at(0) && cardsRem !=0){
if( GameBoard::pool[col].size() > 1 ){
GameBoard::pool[col].pop_back();
cardsRem--;
}
if(GameBoard::pool[col].size() <2){
toDel.insert ( toDel.begin() , col );
//GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
size--;
}
}
}
}
for(int i = 0; i< toDel.size(); i++){
GameBoard::pool.erase(GameBoard::pool.begin() + toDel[i]);
}

Floating point exceptions,segmentation faults and similar errors

I sometimes get this type of errors. My question is, is there a way to find out information about when and where(which line) exactly this error occurs? I'm on ubuntu linux 14.04. Using sublime and g++.
Here is my current code. I get a floating point exception in this. It takes 2 vectors and prints the numbers that are divisible by every element of the first set and can divide every element of the second set.
Posting the code is kinda irrelavant to the topic but it forced me to find a decent way to debug the mentioned error types. This is my first time asking a question here, go easy on me.
int main()
{
vector<int> firstVector;
vector<int> secondVector;
firstVector = {2,4};
secondVector = {16,32,96};
auto it = firstVector.begin();
for (int i = 1; i <= 100; ++i)
{
it = firstVector.begin();
for (; ; ++it)
{
if(i%(*it)!=0)
break;
if(it==firstVector.end())
{
it=secondVector.begin();
while(it!=secondVector.end())
{
if((*it)%i!=0)
{
it=firstVector.begin();
break;
}
it++;
}
}
if(it==secondVector.end())
break;
}
if(it==secondVector.end())
cout << i << endl;
}
return 0;
}
I guess there is a problem in iteration over firstVector and secondVector. In second loop:
auto it = firstVector.begin();
for (; ; ++it)
{
it is iterator for firstVector. But in the next loop:
it=secondVector.begin();
while(it!=secondVector.end())
{
it becomes iterator for the secondVector. Iteration over it continues in the outer for loop after this while loop. You increment ++it and access elements if(i%(*it)!=0) at and after the .end() element. This leads to UB:
This element acts as a placeholder; attempting to access it results in undefined behavior.
This question is kind of a two-parter. Since Nikita already addressed your code...
My question is, is there a way to find out information about when and where(which line) exactly this error occurs?
Use gdb name-of-executable to debug on Linux. Simply run and the program will break when a seg fault occurs or, I believe, a fatal exception is thrown. It will tell you the file name and line number.
You can also look up more gdb commands, like here: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

c++ boost map program crash after erase

I have a problem and dont know how to proper solve it or WHY the error appear.
To my problem:
I have 1 loop which execute a function every 2 seconds. That functions does a for() function and erase all entrys which remaining time is at 0. If remaining time is not 0 then it will decrease it by 2000 (2sec).
But after erasing an entry the program crashes...
boost map:
boost::unordered_map<unsigned int, sBUFF_INFO*> p_BuffInfo;
function which get executed from 2 seconds loop
void CSkill::DecreaseAllBuffRemTime()
{
for( itertype(p_BuffInfo) it = p_BuffInfo.begin(); it != p_BuffInfo.end(); it++ )
{
sBUFF_INFO* buff = it->second;
if(buff != NULL)
{
if(buff->dwTimeRemaining <= 0)
{
this->DelPcBuffInfo(buff->tblidx)
}else{
buff->dwTimeRemaining -= 2000;
}
}
}
}
DelPcBuffInfo function:
void CSkill::DelPcBuffInfo(unsigned int tblidx)
{
p_BuffInfo.erase(tblidx);
}
Now after DelPcBuffInfo gets executed the program crash.
At this line it crash:
sBUFF_INFO* buff = it->second;
At debug:
Unhandled exception at 0x00578e0f in GameServer.exe: 0xC0000005:
Access violation reading location 0xddddddd9.
it + node_ = hash_ CXX0030; Error: expression cannot be evaluated
I dont really understand why this error appear..
edit:
If I add a "return" after this->DelPcBuffInfo(buff->tblidx) then the program dont crash..
Adding or removing items from a container will often invalidate your iterators. Check the documentation for unordered_map iterators or here: Iterator invalidation in boost::unordered_map
the correct idiom is
for( itertype(p_BuffInfo) it = p_BuffInfo.begin(); it != p_BuffInfo.end(); )
{
sBUFF_INFO* buff = it->second;
if(buff != NULL)
{
if(buff->dwTimeRemaining <= 0)
{
it = this->DelPcBuffInfo(buff->tblidx)
}else{
buff->dwTimeRemaining -= 2000;
it++;
}
}
}
ie dont increment in the loop. Instead increment if you dont delete otherwise have the delete operation return the new iterator. Thats why remove returns an iterator pointing at the next element
This is courtesy of the awesome Scott Myers
To add to the existing answers pointing out the erase-iterator idiom: The reason for you crash is that the iterator it is invalidated due to the removal of the element. Thus, the increment on the (invalid) operator causes undefined behaviour and it will point to some arbitrary memory block. Dereferencing the "iterator" then crashes your program.
To avoid this problem, apply the idiom as demonstrated in the other answers, that is
* Use the iterator version of erase. It returns an iterator to the next element ( which may be end())
* Use the return value of this erase as new value of it. Since it already points to the next element, do not increment again (otherwise you may skip an element in your map or cause undefined behaviour if it already points to the end of the map.
* Only increment the iterator yourself, when you did not erase an element.
Note: If your intention is to get rid of the sBUFF_INFO element completely upon removal from the map, your programm shows a memory leak. Erasing the pointer from the map does not delete the pointed-to memory. You need to delete the pointee yourself (or use an appropriate smart pointer).
void CSkill::DecreaseAllBuffRemTime()
{
auto it = p_BuffInfo.begin();
while( it != p_BuffInfo.end() )
{
sBUFF_INFO* buff = it->second;
if(buff)
{
if(buff->dwTimeRemaining <= 0)
{
// probably delete buff too
it = p_BuffInfo.erase(it);
} else {
buff->dwTimeRemaining -= 2000;
++it;
}
} else {
++it;
}
}
}

C++ Access Violation Reading location 0x003AE000 when trying to erase from vector

I am getting an error when I try to erase an item from an vector if the item is set to not alive by a boolean. I have tried searching the net but havn't found anything about it. I have tried to find different ways to delete elements on index x in a vector and found the function: vector.erase(vector.begin() + index)
So when I try using it in my for loop I get access violation reading location pointing at the erase function line.
Code for the loop where the error is:
if (!player.getBullets().empty())
{
for (int x = 0; x < player.getBullets().size(); x++)
{
//Check for projectiles whos status is dead.
if (!player.getBullets()[x]->getAlive())
{
//Erase the element at position x.
player.getBullets().erase(player.getBullets().begin() + x);
}
}
}
Don't reinvent the wheel, especially not the really difficult one that can go under water and up walls. Use a ready-made one:
#include <algorithm>
player.getBullets().erase(
std::remove_if(player.getBullets().begin(),
player.getBullets().end(),
[](Projectile * p) -> bool { return !p->getAlive(); }),
player.getBullets().end());
(I'm assuming that Bullet is the same as decltype(player.getBullets())::value_type, i.e. the element type of the bullets container. Adjust to suit.)
It's much easier to erase correctly if you use an iterator instead of an index. An (almost) direct conversion of your code:
vector<Projectile*> bullets = player.getBullets();
for (vector<Projectile*>::iterator x = bullets.begin(); x != bullets.end(); )
{
//Check for projectiles whos status is dead.
if (!(*x)->getAlive())
{
//Erase the element at position x.
x = bullets.erase(x);
}
else
{
++ x;
}
}
Note that this only works with a local copy of the vector. If you want to update the vector in the player class itself, you will need to change getBullets to return a reference:
vector<Projectile*> &Sprite::getBullets()
{
return bullets;
}
And then for the loop:
vector<Projectile*> &bullets = player.getBullets();
Though the loop is invalid because counter x is increased while the size of the vector is decreased and as the result not all the vector is traversed I do not see the reason of the access violation. I think that the problem is related to objects stored in the vector.

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?