priority_queue Invalid Heap - Debug Assertation Fault - c++

I'm experiencing huge problem with priority_queue STL container.
I'm using it to sort objects by parameter x.
Code used to compare by objects parameter.
class CompareX {
public:
bool operator() (MyClass *e1, MyClass *e2) {
return e1->get_x() > e2->get_x();
}
};
Definition of priority_queue in main:
priority_queue<MyClass*, vector<MyClass*>, CompareX > my_queue;
Sorting works fine, but here's code where I get Debug Assertation Fault - Invalid Heap:
if(condidion == false)
{
double n = 200;
my_queue.top()->modifyX(clock, n); //Here I modify parameter X (it becomes bigger)
my_queue.push(my_queue.top());
my_queue.pop();
}
My goal is to modify parameter X to a bigger one, and re insert object into my_queue to sort it again. What's wrong?

Related

size of a static vector

I am using a static vector inside a member function and pushing back values into that vector;
but the size of vector is only 1 for three function calls.
I am not sure how to make MVCE for this as in MVCE it is working fine for me too, so the problem is obviously some other part of code.
I just want to know or have an idea under which circumstances would my static vector give me such results.
class X
{
//...
};
template <typename T>
void test(T a)
{
std::cout<<"Function called \n";
static std::vector<X> vec;
std::lock_guard<std::mutex> lock(mx);
//Doing something else with T
X obj;
vec.push_back(obj);
std::cout<<"no of elements in vec is "<<vec.size()<<"\n";
}
The output coming is
Function called
no of elements in vec is 1
Function called
no of elements in vec is 1
Function called
no of elements in vec is 1
The member function is called from the CPPREST http_client request call.
Note that the template instantiations with different type are irrelevant. It means if you called test() three time with different type T, then three irrelevant test() will be instantiated, with 3 diffrent instances of vec. That's why you're getting the result that their size are all 1.
Your request call probably looks similar to this
int i = 1;
float f = 2.5;
char c = 'A';
test(i);
test(f);
test(c);
If you add
test(i);
Then vec.size() for test(int) will be 2
While vec.size() for test(float) and test(char) will stay 1.
You can read more about the behavior of static variables in templates here http://www.geeksforgeeks.org/templates-and-static-variables-in-c/

std::sort with personal class returns segmentation fault

I have a small problem with std::sort.
When I try to sort an allocated array of objects using the override of the "<" function with std::sort, I get a segmentation fault.
You can see the problem here below in a toy example: In my class point, I allocate an array of personal objects key (especially I allocate the memory for an array v). Its elements are initialized, and then I try to sort this array.
With small sizes (for the array v and the array to sort), I get no error, and valgrind returns none.
For big sizes, I get a segmentation fault, and valgrind outputs a lot of errors I don't understand.
Could you help me?
Thanks!
using namespace std;
#include <stdlib.h>
#include <iostream>
#include <algorithm>
class key
{
public :
int size;
double *v, f;
key() {}
key(const key & k)
{
size = k.size;
f = k.f;
v = (double*)malloc(size*sizeof(double));
for(int i=0;i<size;i++)
v[i]=k.v[i];
}
~key()
{
free(v);
}
bool operator<(const key& other) const
{
return f<other.f;
}
void init(int s)
{
size = s;
v = (double*)malloc(size*sizeof(double));
for(int i=0;i<size;i++)
v[i]=((double)rand()/(RAND_MAX));
}
};
class point
{
public :
key *k;
point() {}
point(int param1, int param2)
{
k = (key*)malloc(param1*sizeof(key));
for(int i=0;i<param1;i++)
{
k[i].init(param2);
k[i].f=param1-i;
}
std::sort(k,k+param1);
free(k);
}
};
int main(int argc, char **argv)
{
point p(100,21200); // segmentation fault!
//point p(10,2); // no segmentation fault!
return 0;
}
Your classes need a copy constructor (or a move constructor) and a custom assignment operator because they manage raw pointers (resources). Otherwise when std::sort performs assignments of your point or key objects, the corresponding objects' data is not deep copied, but only the pointers are copied. Your destructor then ends up freeing the memory for pointers that point to the same memory address, which results in undefined behaviour (you'll often get a segfault on Linux/Unix). Also, remove those malloc/frees and replace them by new[]/delete[]. Or better, use standard containers like std::vector.
Note that some compilers can catch this issues at compile time. For example, gcc with -Weffc++ spits out an warning:
warning: struct Foo has pointer data members [-Weffc++]
but does not override Foo(const Foo&)

Error inserting custom class to map as value

I'm having trouble understanding why this isn't working as I expect it to. It may be that I'm using Visual Studio 2013, but hey.
This code is part of the item randomization system in a game engine I'm writing.
// the chance a rarity will have a given number of affixes
std::unordered_map<ItemRarities, ChanceSelector<int>> affixCountChances = {
std::pair<ItemRarities, ChanceSelector<int>>(ItemRarities::Cracked,
{ ChanceSelector<int>(
{ ChancePair(int, 100, 0) }) }),
std::pair<ItemRarities, ChanceSelector<int>>(ItemRarities::Normal,
{ ChanceSelector<int>(
{ ChancePair(int, 80, 0),
ChancePair(int, 20, 1) }) }),
// snip for conciseness (there are 3 more)
};
And this is the ChanceSelector class:
using Percentage = int;
#define ChancePair(T, p, v) std::pair<Percentage, T>(p, v)
template <class T>
class ChanceSelector
{
private:
std::unordered_map<T, Percentage> _stuff;
public:
ChanceSelector()
{
}
~ChanceSelector()
{
if (_stuff.size() > 0)
_stuff.clear();
}
ChanceSelector(std::initializer_list<std::pair<Percentage, T>> list)
{
// snip for conciseness
}
T Choose()
{
// snip for conciseness
}
};
The above code compiles fine but I have two questions:
I don't understand why using ChanceSelector in std::pair requires a default constructor. Explicitly, it looks like I'm calling the constructor with the initializer list.
When the applications runs, it crashes with: Unhandled exception at 0x01762fec in (my
executable): 0xC0000005: Access violation reading location 0xfeeefeee.
Number 2 goes away if I only have one item in that map or if I change the definition of affixCountChances to std::unordered_map<ItemRarities, ChanceSelector<int>*> (and adjust the rest accordingly). The error dumps me at this code in list:
for (_Nodeptr _Pnext; _Pnode != this->_Myhead; _Pnode = _Pnext)
{
_Pnext = this->_Nextnode(_Pnode); // <-- this line
this->_Freenode(_Pnode);
}
Further inspection reveals the error happened in the destructor. _stuff is empty:
~ChanceSelector()
{
if (_stuff.size() > 0)
_stuff.clear();
}
It is legitly calling the destructor. Items are being removed from _stuff but I don't see why it would be calling the destructor. The crash happens after all items have been constructed and affixCountChances contains all items. I would assume that means it's destroying all the temporaries it created but I don't see why it would be creating temporaries.
Edit:
Constructor of ChanceSelector:
ChanceSelector(std::initializer_list<std::pair<Percentage, T>> list)
{
int total = 0;
int last = 100;
for (auto& item : list)
{
last = item.first;
total += item.first;
_stuff[item.second] = total;
}
// total must equal 100 so that Choose always picks something
assert(total == 100);
}
To answer your two questions:
std::pair requires a default constructor, because you can do something like
std::pair<int, MyClass> myPair();
which creates a copy of your class using the default constructor (The values of the pair are actual values and not references):
// MSVC implementation
template<class _Ty1,class _Ty2>
struct pair
{ // store a pair of values
typedef pair<_Ty1, _Ty2> _Myt;
typedef _Ty1 first_type;
typedef _Ty2 second_type;
pair()
: first(), second() // Here your class gets default constructed
{ // default construct
}
// .....
_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
};
The template of the pair gets fully implemented, so you need a default constructor event if you are not using the line above.
One way to avoid this dependency is to use pointers in the std::pair, this then sets the default value of the second value of the pair to nullptr:
std::pair<int, MyClass*> myPair();
0xFEEEFEEE indicates that the storage, where your pointer itself was stored has already been deleted (e.g. working on a deleted class reference).
This deletion seems to occur somewhere outside the code you have posted here.
For more Magic Numbers see Magic Numbers on Wikipedia
Edit:
Additionally, the contents of the initializer list do not exist after the constructor call. You might have there a reference copied instead of the actual object, which then gets deleted. The msvc implementation of the std::unordered_map uses a std::list as base for storing items. I'm not able to give your more information about this with the given code.
Initializer list and lifetime of its content
Edit 2: I was able to reproduce the error with your given code, it was not the content of the initializer_list ctor.
The problem seems to be the lifetime of the objects inside the initializer list.
When I move the declaration of the pairs for the unordered map out of the initializer_list for the unordered map, everything works fine:
std::pair<ItemRarities, ChanceSelector<int>> pair1( ItemRarities::Cracked,
{ ChanceSelector<int>(
{ ChancePair( int, 100, 0 ) } ) } );
std::pair<ItemRarities, ChanceSelector<int>> pair2( ItemRarities::Normal,
{ ChanceSelector<int>(
{ ChancePair( int, 80, 0 ),
ChancePair( int, 20, 1 ) } ) } );
std::unordered_map<ItemRarities, ChanceSelector<int>> chances = {
pair1,
pair2
};
I'm not completely sure why this is a problem, but I think is comes from the {} in the initializer list, those objects might get deleted, when leaving the first {} and before entering the actual intializer_list for the unordered_map

Dynamic Polymorphic Memory Container - Return Value Incorrect

I am currently working on an dynamic memory container.
Basic idea of the class is that you should be able to get the iterator of an object if you really do not know it, without the use of a for loop throughout all the elements to boost performance. The issue I have is the following; when you pass your pointer address to the object you want to get the iterator of it type casts the object into the extended memory containers structures type. This type contains an extra element, an integer. (IteratorNum)
When following the code the integer within the function is set to correct value, as below would be 50. But when the returned value is set into the local integer used in the main function it is 200? I've been adding watches and cannot figure out how it is possible that the function returns 50 but value gets set to 200.
template <typename DataType> class MemoryContainer {
public:
struct LevelData : DataType
{
int element;
};
DataType &New()
{
elements++;
//Reallocate the size of the array
ld = (LevelData*)realloc(ld, sizeof(LevelData) * elements);
//Set the iteratorNumber
ld[elements - 1].element = elements - 1;
return ld[elements - 1];
}
DataType *reserve(int num)
{
return calloc(num, sizeof(DataType));
}
DataType &operator[](int i)
{
return ld[i];
}
bool inArray(DataType *type)
{
//Compare memory addresses and see if it's within.
return (type >= &ld[0]) && (type < &ld[elements - 1]);
}
static unsigned int getIterator(DataType *type)
{
// v this is 50, but in main says returns 200.
return ((LevelData*)type)->element;
}
MemoryContainer()
{
elements = 0;
}
~MemoryContainer()
{
free(data);
}
private:
unsigned int elements;
LevelData *ld;
};
struct Effective
{
//Set it to polymorphic classes
virtual void dummy()
{
}
char * testvar;
Effective(char * c)
{
testvar = c;
}
Effective(){}
};
MemoryContainer<Effective> myContainer;
int _tmain(int argc, _TCHAR* argv[])
{
//Create 200 elements in the array
for(int i = 0; i < 200; i++)
myContainer.New().testvar = "E";
//Add pointer for testing purposes to get the iterator.
Effective * pointer = &myContainer[50];
//Test setting it's value
pointer->testvar = "HEHEHE";
//Get iterator of our pointer in the array
unsigned int i = myContainer.getIterator(pointer);
printf(pointer->testvar);
system("PAUSE");
return 0;
}
I suspect it is the visual studio debugger getting confused between your two i variables. If you print out the value of i, it will print correctly. If you change the name of your variable to something else, the value shows as 50 in the debugger.
That said, your code is a mish-mash of c and c++ and won't work correctly with anything that requires a copy constructor. I would suggest at the very least using new [] rather than realloc.
Also, any user of this collection who tries to store a class with a member variable called element is going to get mighty confused.
The unsigned int i in the main function really has a value of 50, but the debugger is confusing it with the i declared in the for loop (I reproduced this with Visual Studio 2013). If you cout i it will be 50, and if you change the variable name it will show up as 50 in the debugger. I've never seen this problem before so I wonder if it might be due to your use of malloc/realloc/free with C++ objects.

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

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.