C++ std::vector::clear() crash - c++

I've got a program where I have a std::vector as a member of a class:
class Blackboard
{
public:
inline std::vector<Vector2<int> > GetPath()
{ return m_path; }
inline void SetPath(std::vector<Vector2<int> > path)
{ m_path = path; }
inline void ClearPath()
{ if(m_path.size() > 0) m_path.clear(); }
private:
std::vector<Vector2<int>> m_path;
};
Where the Vector2 class is defined as:
template <class T>
class Vector2
{
private:
T m_x;
T m_y;
public:
Vector2(void)
{ m_x = 0; m_y = 0;}
Vector2(T x, T y)
{ m_x = x; m_y = y;}
~Vector2(void)
{ }
inline T x() const
{ return m_x; }
inline T y() const
{ return m_y; }
// ...
};
And at some point I call:
m_blackboard.ClearPath();
This works fine in debug, but crashes in release with the "Microsoft Visual Studio C Runtime Library has detected a fatal error in Test2.exe." message.
The call stack, at the last point where I can still see shows that:
Test2.exe!std::vector<RBT::Vector2<int>,
std::allocator<RBT::Vector2<int> > >::erase
(std::_Vector_const_iterator<RBT::Vector2<int>,
std::allocator<RBT::Vector2<int> > >
_First_arg={m_x=15 m_y=7 },
std::_Vector_const_iterator<RBT::Vector2<int>,
std::allocator<RBT::Vector2<int> > >
_Last_arg={m_x=15 m_y=8 }) Line 1037 + 0xe bytes C++
Here is where I'm calling the code that ends up crashing:
BTNode::Status GoToDestBehavior::Update()
{
BTEntityData::Node* node = m_dataRef->m_bTree.GetNode(m_index);
if(node->m_state == BTNode::STATE_READY)
{
BehaviorTree::RequestDeferredAction(Batch::PATHFIND, m_dataRef->m_entityID);
return BTNode::STATE_RUNNING;
}
else if(node->m_state == BTNode::STATE_RUNNING)
{
std::vector<Vector2<int>> path = m_dataRef->m_blackboard.GetPath();
EntitySystem::Entity* entity = EntitySystem::GetEntity(m_dataRef->m_entityID);
Assert(entity != NULL, "Invalid entity\n");
Assert(entity->HasComponent(Component::PHYSICS_COMP), "Associated entity must have physics component to move\n");
int phyIndex = entity->GetComponentIndex(Component::PHYSICS_COMP);
PhysicsSystem::PhysicsData * physicsData = PhysicsSystem::GetComponent(phyIndex);
Assert(physicsData != NULL, "Invalid physics data\n");
// Path is empty, so finish
if(path.size() == 0)
{
physicsData->m_dir = Direction::NONE; // Stop because we are here
return BTNode::STATE_SUCCESS;
}
// Remove last element if we are at it
//LogFmt("Size of vector %d\n", path.size());
Vector2<int> last = path.back();
if(last.x() == physicsData->m_posX && last.y() == physicsData->m_posY)
{
path.pop_back();
}
// Last node of the path has been transversed
if(path.size() == 0)
{
physicsData->m_dir = Direction::NONE; // Stop because we are here
m_dataRef->m_blackboard.ClearPath();
return BTNode::STATE_SUCCESS;
}
Vector2<int> step = path.back();
physicsData->m_dir = Direction::VectorToDirection(physicsData->m_posX, physicsData->m_posY, step.x(), step.y());
if(physicsData->m_dir == Direction::NONE)
{
m_dataRef->m_blackboard.SetPath(path);
return BTNode::STATE_FAIL;
}
m_dataRef->m_blackboard.SetPath(path);
return BTNode::STATE_RUNNING;
}
return BTNode::STATE_ERROR;
}
I don't know why it's behaving like this. Most similar issues I've found online have the problem of calling clear on an empty array, but I have a guard against that, so it shouldn't be the issue.
The other thing I can think of is my Vector2 class requiring some kind of copy constructor or something for when I add elements to the vector, but in the end it's just 2 ints, so I don't know why that might be failing.
I've been over this code too much and might be missing something obvious.

It's perfectly fine to call clear on an empty container of any sort.
Using my psychic debugging skills, I have determined that in code you aren't showing us you're accessing elements of the vector that don't actually exist (possibly before you inserted them, and probably with operator[]). Usually element creation is done through resize, push_back, or insert.
The other possibility is that you have another memory corruption somewhere in your program.

I found an issue I had due to a change in data format. The std::list I was using changed from a pointer to a list to directly the list. This started causing all sorts of errors that checking for the size of the list did not solve and were caused by a ZeroMemory()/memset() call that wiped out all of the tracking data of the list, since it was now part of the class instead of a pointer to the list.
If you have an empty list and call .clear() on it with a crash, chances are you have messed up the internal tracking memory as mentioned by Mark in his answer. Look for a place where you are doing memory clearing on containing classes and the like as the most likely culprits.

I know it's been 8 years, but I thought too I had this problem when I was destroying an empty bst into which my code was sending a nullptr value to the __p variable in the implementation of "new_allocator.h". This __p is needed to never be null, as mentioned in the file itself!
// __p is not permitted to be a null pointer.
The solution is not sending anything if you don't have something to send, basically.

Related

binary '==': no operator found which takes a left-hand operand of type 'Enemy' (or there is no acceptable conversion)

I'm making a game and I'm trying to find enemies with the bool shouldDie == true.
I have an Enemy std::list and personally I have no idea what's wrong with the code.
If an enemy has shouldDie == true I'll just have an animation playing.
Hopefully you can help me understand why I get the error.
Also I have no overloaded == operator, I've searched online and I'm not sure if it's necessary...
bool foundEnemy(Enemy& enemy)
{
return enemy.shouldDie == true;
}
void Enemy::PlayDeathAnimation(std::list<Enemy>& enemies)
{
dead = true;
auto it = std::find_if(enemies.begin(), enemies.end(), foundEnemy); // where I think the error is
auto enemy = std::next(it, 0);
if (animationClock.getElapsedTime().asSeconds() >= 0.05f)
{
enemy->icon.setTextureRect(animationFrames[animationCounter]);
if (animationCounter >= 8)
{
enemies.remove(*enemy);
}
animationCounter++;
animationClock.restart();
}
}
class Enemy : public Entity
{
public:
Enemy() {}
Enemy(sf::Vector2f position, sf::Texture* texture,Player* target);
~Enemy();
void Update(sf::RenderWindow* window, float tElapsedTime);
void Draw(sf::RenderWindow* window);
void Fire(float tElapsedTime);
void CheckBullets();
void CheckEnemyBullets();
void CheckHealth();
void SetPosition(float x, float y);
bool shouldDie = false;
void PlayDeathAnimation(std::list<Enemy>& enemies);
private:
bool dead = false;
sf::Texture* deathSpriteSheet;
std::vector<sf::IntRect> animationFrames;
std::vector<Bullet> bullets;
sf::RectangleShape origin;
sf::RectangleShape aim;
Player* target;
int animationCounter = 0;
sf::Clock animationClock;
};
The error is actually not where you think it is, but few lines below.
if (animationCounter >= 8)
{
enemies.remove(*enemy); // here
}
You are using std::list::remove function, which will search for any elements of the list matching given element and removes those. To know which element is the same as given, it needs to know how to compare them, thus the need for operator ==
Use std::list::erase() instead - this function accepts an iterator and will remove exact element you point to.
if (animationCounter >= 8)
{
enemies.erase(enemy); // no dereference of the iterator
}
Side note - compiler is very useful tool. If it detects an error, it will point you to a direct line and column where it occurred, although sometimes this piece of information is very well hidden in a ton of other (less useful) prints.
If you don't understand the language of the compiler (yet), you can copy and paste the whole error message into your SO question, this will help us diagnose error faster.

Misunderstanding in use of class variables from a header file

struct TodoItem
{
std::string todo;
};
const int MAX_STACK_SIZE = 5;
class TodoStackArray
{
public:
TodoStackArray(); //confusion here<---
bool isEmpty();
bool isFull();
void push(std::string todoItem);
void pop();
TodoItem* peek();
/* for grading purposes we need these following methods */
int getStackTop() { return stackTop; }
TodoItem** getStack() { return stack; }
private:
int stackTop;
TodoItem* stack[MAX_STACK_SIZE];
};
Above, is some declarations and a class from a header file for a current assignment. Our duty was to implement a stack program using this header file. However, I am a little confused as to the purpose of the TodoStackArray() in the Header File. Is this supposed to be a base constructor? Am I supposed to use it for anything??
I understand that this is somewhat situation specific but given that stack Arrays are STL I figured you might all be able to provide some insight. Thanks!
In case you want to see what I did with this header file...
TodoStackArray::TodoStackArray() //This, unsurprisingly, produces an error.
{
stackTop = -1;
stack[stackTop];
}
bool TodoStackArray::isEmpty()
{
return (stackTop == -1);
}
TodoItem* TodoStackArray::peek()
{
if(stackTop ==-1)
{
cout<< "Stack empty, cannot peak."<<endl;
}
else
{
return(stack[stackTop]);
}
}
bool TodoStackArray::isFull()
{
return(stackTop == 4);
}
void TodoStackArray::push(std::string todoItem)
{
if(stackTop >= 5)
{
cout<<"Stack full, cannot add new todo item."<<endl;
}
else
{
stack[stackTop++];
stack[stackTop]->todo = todoItem;
}
}
void TodoStackArray::pop()
{
if(stackTop == -1)
{
cout<<"Stack empty, cannot pop an item."<<endl;
}
else
{
stackTop--;
}
}
Also, to be clear, we were not provided driver software. They will be assessing from their own stuff so we have to write our own driver software to test our functions. Hence the lack of any Main implementation.
Yes, TodoStackArray::TodoStackArray() really is your class' default constructor.
What you are supposed to do with it just as with any default constructor:
How are the class members supposed to be initialized if I create a new TodoStackArray?
The answer depends on what your class is supposed to look like in its initial state.
In you situation, "by default" a stack is empty. Setting the stackTop to -1 was not a bad idea and the rest of your implementation is consistent with that (stackTop == -1 clearly means "empty stack").
The odd thing that happens in your constructor is this:
stack[stackTop];
What is, according to you, the purpose of this line? You are reading the value in your array at a negative index, and we all know this kind of things never end well.
Constructors are made to initialize your data. Here you are reading something you didn't initialize at an index that doesn't exist. Doesn't make much sense, does it? :)
Just get rid of this line and you should be able to move on. Here is an equivalent implementation using member initializer list (which are considered nicer):
TodoStackArray::TodoStackArray() : stackTop(-1)
{
// notice: no body required here
}
Have fun!

Position in Member Declaration Breaks Code?

A while ago I asked a question on why the following code did not work:
std::vector<std::vector<std::vector<Tile_Base*>>> map_tile; // This is located in Map object. See below.
int t_x, t_y;
t_x = t_y = 200;
map_tiles.begin(); // clear(), resize() and every other function still causes problems
The thing is, is that it should have worked, yet Visual Studios 2012 throws an exception when the resize function is called. The exception pointed to this piece of code:
*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
located in xutility. It said that there was an violating on access to reading the memory. I thought maybe somehow I lost access to the member along the way? (Using VS' watch I saw the memory was not corrupted)
So, I fiddled around with the code and tried to figure out what could possibly be going wrong, and after awhile I moved the map_tiles object down to the bottom of the list, and it worked:
// WORKS
class Map {
std::vector<Tile_Base*> spawn_tiles;
// map tile specific
bool Is_Valid(int,int);
std::string name;
std::vector<std::vector<std::vector<Tile_Base*> > > map_tiles;
public:
// ...
}
// DOESN'T WORK
class Map {
std::vector<std::vector<std::vector<Tile_Base*> > > map_tiles;
std::vector<Tile_Base*> spawn_tiles;
// map tile specific
bool Is_Valid(int,int);
std::string name;
public:
// ...
}
Any help pointing out what went wrong? I can't come up with any reasonable explanation.
A vector<T> comprises two discrete sets of data: the internal state and the array of Ts. The internal state - capacity, size, pointer - is separate from the array. The issue you're describing is normally caused by something overwriting the vector object, i.e the internal state. To track this down easily you could use a container class:
typedef std::vector<std::vector<std::vector<Tile_Base*> > > maptiles_t;
class CMapTiles
{
unsigned int m_guard;
maptiles_t m_tiles;
enum { Guard = 0xdeadbeef };
public:
CMapTiles() : m_guard(Guard), m_tiles() {}
~CMapTiles() { assert(m_guard == Guard); }
void Check()
{
#if defined(DEBUG)
if (m_guard != Guard)
DebugBreak();
#endif
}
void Resize(size_t x, size_t y)
{
Check();
auto init = std::vector<std::vector<Tile_Base*> >(y/32);
m_tiles.resize(m_x / 32, init);
Check();
}
const maptiles_t& tiles() const { Check(); return m_tiles; }
maptiles_t& tiles() { Check(); return m_tiles; }
};
And instead of using std::vector<...> map_tiles have CMapTiles map_tiles, and then when you want to get at the vector, map_tiles.tiles().
Hope this helps.

All elements in a c++ vector point to the same element

I'm a complete beginner in c++ and everything has been going on well until now. I'm new to the idea of pointers (I'm from python), and I have this weird error.
So basically, I created this "SearchNode" class, and found below is one of it's methods "getChildren" which should return a vector of other SearchNode instances, representing the possible cells to which a Knight (chessboard) could travel from it's current state. (BFS)
That said, when I finish pushing into my vector, all the elements suddenly point to 1st element only. Could someone help me out here?
PS: it's a similar problem to c++ push_back doesn't work as it is supposed ... but unlike Angela (who's was writing her own compiler), I'm a total beginner in c++. Your help with be greatly appreciated.
UPDATE
I got rid of the int*, and used array for my state. I could now successfully search the graph (therefore the states are ok) and find the shortest path, but I couldn't seem to reconstruct the path.
To test, I started at {0,0} and could find {4,4}, but the path, according to the getPath method was {4,4}, {3,6}, {3,6}, {3,6} ... (infinite loop of {3,6}). Is there something wrong with my parent pointers, or my getPath function? Thanks for your support in advance.
//Search class
class SearchNode
{
public:
//Variables
SearchNode *m_parent;
array<int,2> m_state; //I don't understand typedef's yet, will use them when I'm clearer with them :)
//Normal Constructor
SearchNode(array<int,2>& state_, SearchNode *parent_=nullptr) :
m_state(state_),
m_parent(parent_)
{}
//Method to get Next reachable states. Returns instances of SearchNode.
vector<SearchNode> getChildren()
{
int legalMoves[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
vector<SearchNode> children;
children.reserve(8);
for(int i=0; i<8; i++)
{
int x = (m_state[0] + legalMoves[i][0]);
int y = (m_state[1] + legalMoves[i][1]);
if( (x>-1) and (x<9) and (y<9) and (y>-1)) // Within the bounds of the board
{
array<int,2> childState = {x,y};
SearchNode childNode = SearchNode(childState,this);
children.push_back(childNode);
}
}
return children;
}
void getPath()
{
cout<<"\nPath: ";
cout<< this->print();
SearchNode current = *this;
unsigned int counter = 1;
while((current.m_parent!=nullptr) and counter< 10)
{
counter++;
cout<< (current.m_parent)->print();
current = *(current.m_parent);
}
cout << (current.m_parent)->print();
}
string print()
{
stringstream out;
out << "{" << this->m_state[0] << "," << this->m_state[1] << "} ";
return out.str();
}
};
Lots of mistakes and errors, I strongly suggest you turn up the warning level in your compiler so you can get more information. With GCC/G++/Clang, try "-Wall" or "-Wextra", as moshbear points out.
Your nodes never get assigned the "parent" value, you're creating a "shadow" local variable called "parent" and assigning that. To avoid common errors like this, use a prefix or postfix for member variable names to separate them from local names, e.g. "m_parent" or "_parent".
You don't assign default values in your constructor, you explicitly leave the values uninitialized.
SearchNode()
{
//do nothing
}
and then you introduce this garbage data in your pointer-based constructor, what you probably want is
SearchNode() : parent(NULL), state(NULL) {}
Your copy constructor is a disaster. You need to read up on and understand pointers and local variables.
//Start Node constructor. Still looking for an equivalent for null.
SearchNode(int *state)
{
int genericStartState[2] = {-1,-1};
SearchNode blankParent = SearchNode();
SearchNode genericStart = SearchNode(genericStartState,&blankParent);
this->parent = &genericStart;
this->state=state;
}
Firstly, "blankParent" here is a local variable containing random data because of your current copy constructor. Secondly, you're taking the address of it - of a private, local variable, which is about to stop existing when you hit the "}" at the end of the routine.
"genericStartState" is also about to go out of scope.
And aside from that, I don't think you want or need this particular constructor.
But fundamentally, the bug in your subject, is because you do the same thing in your assignment loop -- you use a temporary, local array to store the new values, and then pass a pointer to that to your constructor. Since you are taking the address, it will be the same every loop.
int childState[2] = { x, y };
SearchNode childNode = SearchNode(childState,this);
This is why all of your nodes have the same state - because they all point to the same memory location (edit: as pointed out by DyP, that side-effect isn't something you can count on, just an artefact of ordering in this case).
It might be easier for you to use simple array of ints rather than a pointer in your node structure.
Here's how the constructor side of things might look, if your compiler is VisualStudio 2012 or G++ 4.8 or Clang 4.2.
class SearchNode
{
public:
typedef std::array<int, 2> State;
private:
// I use the 'm_' convention for members, 'g_' for globals, 's_' for statics.
SearchNode* m_parent;
State m_state;
public:
//////////
// Default ctor.
SearchNode()
: m_parent(nullptr) // C++11 constant meaning pointer with value 0
, m_state({-1, -1}) // preferred but requires recent C++11 features
{
//m_state[0] = m_state[1] = -1; // had to do this instead for gcc 4.7.3
}
//////////
// Normal ctor
// I use the '_'-postfix convention for parameter names.
SearchNode(SearchNode* parent_, const State& state_)
: m_parent(parent_)
, m_state(state_)
{
}
//////////
// Copy constructor.
// We could do this, but it's the default behavior anyway.
/*
SearchNode(const SearchNode& rhs)
: m_parent(rhs.m_parent)
, m_state(rhs.m_state)
{
}
*/
// Current C++11 compilers let us be explicit and do this:
//SearchNode(const SearchNode& rhs) = default;
// But it's the default behavior so we don't have to do this one at all.
};
The latest C++11 language changes (MSVC > 2012, GCC >= 4.8, Clang >= 4.1) would allow you to replace the first two constructors with
// Kill two birds with one stone and have default parameters on our normal ctor,
// replacing both the default and normal ctor with one function.
SearchNode(SearchNode* parent_ = nullptr, const State& state_ = { -1, -1 }))
: m_parent(parent_)
, m_state(state_)
{
}
If you had a fully C++1y compatible compiler, you could boil all that down to:
class SearchNode
{
public:
typedef std::array<int, 2> State;
private:
// I use the 'm_' convention for members, 'g_' for globals, 's_' for statics.
SearchNode* m_parent = nullptr; // c++1y keyword to replace 'NULL'
State m_state = { -1, -1 };
public:
SearchNode() = default;
SearchNode(const State& rhs_) = default; // not strictly required.
SearchNode(SearchNode* parent_, const State& state_)
: m_parent(parent_), m_state(state_)
{}
};

C++ - Passing Pointer Into Function

I keep on receiving odd unexpected values for my bool testValue. I keep receiving random numbers as I believe it is trying to access another region of memory. I predict it is how my code is setup within my testNumber() function, but I am unsure of how to solve it. This is my logic.
I have set ok to true. Now I assign the memory address of ok to pOk.
void TextBox::lengthTest(bool *pOk, int length) {
bool ok;
if (length < MAX_LENGTH) {
ok = true;
pOk = &ok;
} else {
ok = false;
pOk = &ok;
}
}
bool lengthTestBool = lengthTest(*pOk, length);
cout << lengthTestBool <<;
output:
85
You have a fundamental misunderstanding of how one uses pointers to implement reference semantics. You want to change thing that is pointed to by the pointer:
*pOK = ok;
However, C++ actually supports references semantics natively through reference types, which may be preferable:
void testNumber(bool & OK, int n)
{
OK = true;
// ...
}
Even better, though, is to simply return a bool:
bool testNumber(int n) { /* ... */ }
if (testNumber(x)) //... etc.