vector iterators incompatible Vector Line 251 - c++

I am debugging a code dealing with vectors and iterators. I get an assertion error when I am clicking the "New" button on my GUI. The assertion error is that in the title, with the addition of /vector Line 251.
I have traced the problem to a part of the code attempting to remove an element from a vector. I will post the entire function and then the line that bugs:
int VsuCNTreeNodeManager::deleteTreeNode(RWCString & CNNameToDelete, RWTValSlist<VsuDeletedCN> & deletedCNList)
{
RWCString childName, parentName;
VsuCNTreeNode *pNode;
int i;
int size;
if (!nodeList.contains(CNNameToDelete))
return 1; // Means that CNNameToDelete doest not exist.
pNode = ordCNList[nodeList[CNNameToDelete]];
travForName.reset();
travForName.processElement(pNode);
const RWTValSlist<RWCString> & childNameList = travForName.getNameList();
size = childNameList.entries();
// If it is the Top node that is deleted then
// the VsuCNTreeNodeManager's top node pointer is reset.
if ( pNode == pTopCNTreeNode )
{
pTopCNTreeNode = NULL;
}
for ( i = 0; i < size; i++)
{
//******* How would it possible to have a name not contained in the nodeList
//******* since it has been extracted from the nodeList ?????????????
childName = childNameList.at(i);
if (nodeList.contains(childName))
{
//******* Process that get the Parent List of each deleted Tree Node
//******* The following code unref all the Tree Nodes that was referencing any deleted Tree Node
pNode = ordCNList[nodeList[childName]]; // Get the Tree Node to be deleted
// Fill the deletedCNList
deletedCNList.insert( VsuDeletedCN(childName, pNode->getCN()->hasType()) );
VsuDependencyRemoverVisitor visitor( *pNode );
for (unsigned int k = 0; k < pNode->getParentList().entries(); k++)
{
parentName = pNode->getParentList().at(k)->getCN()->getName();
if ( nodeList.contains(parentName) ) // Check if the parent is not deleted
{
//*** Remove the reference of the deleted tree node from that parent
RWBoolean status;
status = ordCNList[nodeList[parentName]]->removeElem(childName); // Removing the reference that pNode(parent) had on key(Child)
}
}
//******* Remove references on this object from observers.
pNode->resetObserverFlags();
pNode->updateAllObservers(&visitor);
//******* Process that delete all the Tree Nodes in the parentList
nodeList.remove(childName);
}
}
//*****************update Lists********************
size = ordCNList.entries();
int index = 0;
RWTValHashDictionary<RWCString, int> tmpNodeList(rwhash);
//nodeList.clear();
RWTPtrOrderedVector<VsuCNTreeNode> nodeToDelete(childNameList.entries());
for(i = 0; i < size; i++)
{
pNode = ordCNList[index];
childName = pNode->getCN()->getName();
if (!childNameList.contains(childName))
{
tmpNodeList.insertKeyAndValue(childName, index);
index++;
}
else
{
ordCNList.remove(pNode);
typeList[pNode->getCN()->hasType()].treeNodeList.remove(pNode);
// Decrement type counter and if it reach 0 then
// the entry is removed.
if( !typeList[pNode->getCN()->hasType()].treeNodeList.entries() )
typeList.remove(pNode->getCN()->hasType());
nodeToDelete.insert(pNode);
}
}
nodeList.clear();
nodeList = tmpNodeList;
ordCNList.resize(index);
if (!index)
pTopCNTreeNode = NULL;
for( unsigned int j=0; j < nodeToDelete.entries(); j++)
{
delete nodeToDelete[j];
}
return 0;
}
Now the line that bugs is:
RWBoolean status;
status = ordCNList[nodeList[parentName]]->removeElem(childName);
The definition of the removeElem function is:
RWBoolean VsuVE_Collection::removeElem(const RWCString & data)
{
VsuVE_Moveable *pMyObj = elementList.at(nameList[data]);
return removeElem1(pMyObj);
}
The definition of removeElem1 is:
RWBoolean VsuVE_Collection::removeElem1(VsuVE_Moveable *elem)
{
if (elementList.remove(elem) == FALSE) // THE ASSERTION ERROR HAPPENS RIGHT HERE
return FALSE;
//**** Reordering the nameList
nameList.clear();
int size = elementList.entries();
for (int i = 0; i < size; i++)
{
nameList.insertKeyAndValue(elementList.at(i)->name, i);
}
return TRUE;
}
My guess is that the removeElem function is attempting to remove a vector element that isn't there or that is out of the index range, but I am unable to figure out where exactly I can fix this. Any help is appreciated.
Thanks in advance

It's not obvious which particular framework you're using here (Rogue Wave?), but I think it may be possible to deduce the problem.
The key to decoding this assertion is understanding what incompatible iterators means. In general it means that you're trying to do an operation on a pair of items that don't refer to the same thing. For instance: (with standard library containers)
std::vector<int> v1, v2;
for (auto it=v1.begin(); it!=v2.end(); it++) { // <=== iterator incompatible
}
std::vector<int>::iterator it1=v1.begin();
v2.erase(v1); // <==== iterator incompatible
If you dig into the definition of the iterator types you have, then you should find that when the iterator is created it stores a reference back to the container it was created from. If you then perform an operation on two iterators (as in the first case above) then it can detect that they refer to different containers and hence aren't compatible. In the second case you have an operation on a container and an iterator, and so again it will assert that the iterator refers to that container.
In your case it appears that you're trying to remove an element from a container. The framework is asserting that the item isn't in the container (and in fact is probably in another). I suspect that you're deleting an item from the wrong container.

Related

Correctly managing pointers in C++ Quadtree implementation

I'm working on a C++ quadtree implementation for collision detection. I tried to adapt this Java implementation to C++ by using pointers; namely, storing the child nodes of each node as Node pointers (code at the end). However, since my understanding of pointers is still rather lacking, I am struggling to understand why my Quadtree class produces the following two issues:
When splitting a Node in 4, the debugger tells me that all my childNodes entries are identical to the first one, i.e., same address and bounds.
Even if 1. is ignored, I get an Access violation reading location 0xFFFFFFFFFFFFFFFF, which I found out is a consequence of the childNode pointees being deleted after the first split, resulting in undefined behaviour.
My question is: what improvements should I make to my Quadtree.hpp so that each Node can contain 4 distinct child node pointers and have those references last until the quadtree is cleared?
What I have tried so far:
Modifying getChildNode according to this guide and using temporary variables in split() to avoid all 4 entries of childNodes to point to the same Node:
void split() {
for (int i = 0; i < 4; i++) {
Node temp = getChildNode(level, bounds, i + 1);
childNodes[i] = &(temp);
}
}
but this does not solve the problem.
This one is particularly confusing. My initial idea was to just store childNodes as Nodes themselves, but turns out that cannot be done while we're defining the Node class itself. Hence, it looks like the only way to store Nodes is by first creating them and then storing pointers to them as I tried to do in split(), yet it seems that those will not "last" until we've inserted all the objects since the pointees get deleted (run out of scope) and we get the aforementioned undefined behaviour. I also thought of using smart pointers, but that seems to only overcomplicate things.
The code:
Quadtree.hpp
#pragma once
#include <vector>
#include <algorithm>
#include "Box.hpp"
namespace quadtree {
class Node {
public:
Node(int p_level, quadtree::Box<float> p_bounds)
:level(p_level), bounds(p_bounds)
{
parentWorld = NULL;
}
// NOTE: mandatory upon Quadtree initialization
void setParentWorld(World* p_world_ptr) {
parentWorld = p_world_ptr;
}
/*
Clears the quadtree
*/
void clear() {
objects.clear();
for (int i = 0; i < 4; i++) {
if (childNodes[i] != nullptr) {
(*(childNodes[i])).clear();
childNodes[i] = nullptr;
}
}
}
/*
Splits the node into 4 subnodes
*/
void split() {
for (int i = 0; i < 4; i++) {
childNodes[i] = &getChildNode(level, bounds, i + 1);;
}
}
/*
Determine which node the object belongs to. -1 means
object cannot completely fit within a child node and is part
of the parent node
*/
int getIndex(Entity* p_ptr_entity) {
quadtree::Box<float> nodeBounds;
quadtree::Box<float> entityHitbox;
for (int i = 0; i < 4; i++) {
nodeBounds = childNodes[i]->bounds;
ComponentHandle<Hitbox> hitbox;
parentWorld->unpack(*p_ptr_entity, hitbox);
entityHitbox = hitbox->box;
if (nodeBounds.contains(entityHitbox)) {
return i;
}
}
return -1; // if no childNode completely contains Entity Hitbox
}
/*
Insert the object into the quadtree. If the node
exceeds the capacity, it will split and add all
objects to their corresponding nodes.
*/
void insertObject(Entity* p_ptr_entity) {
if (childNodes[0] != nullptr) {
int index = getIndex(p_ptr_entity);
if (index != -1) {
(*childNodes[index]).insertObject(p_ptr_entity); // insert in child node
return;
}
}
objects.push_back(p_ptr_entity); // add to parent node
if (objects.size() > MAX_OBJECTS && level < MAX_DEPTH) {
if (childNodes[0] == nullptr) {
split();
}
int i = 0;
while (i < objects.size()) {
int index = getIndex(objects[i]);
if (index != -1)
{
Entity* temp_entity = objects[i];
{
// remove i-th element of the vector
using std::swap;
swap(objects[i], objects.back());
objects.pop_back();
}
(*childNodes[index]).insertObject(temp_entity);
}
else
{
i++;
}
}
}
}
/*
Return all objects that could collide with the given object
*/
std::vector<Entity*> retrieve(Entity* p_ptr_entity, std::vector<Entity*> returnObjects) {
int index = getIndex(p_ptr_entity);
if (index != -1 && childNodes[0] == nullptr) {
(*childNodes[index]).retrieve(p_ptr_entity, returnObjects);
}
returnObjects.insert(returnObjects.end(), objects.begin(), objects.end());
return returnObjects;
}
World* getParentWorld() {
return parentWorld;
}
private:
int MAX_OBJECTS = 10;
int MAX_DEPTH = 5;
World* parentWorld; // used to unpack entities
int level; // depth of the node
quadtree::Box<float> bounds; // boundary of nodes in the game's map
std::vector<Entity*> objects; // list of objects contained in the node: pointers to Entitites in the game
Node* childNodes[4];
quadtree::Box<float> getQuadrantBounds(quadtree::Box<float> p_parentBounds, int p_quadrant_id) {
quadtree::Box<float> quadrantBounds;
quadrantBounds.width = p_parentBounds.width / 2;
quadrantBounds.height = p_parentBounds.height / 2;
switch (p_quadrant_id) {
case 1: // NE
quadrantBounds.top = p_parentBounds.top;
quadrantBounds.left = p_parentBounds.width / 2;
break;
case 2: // NW
quadrantBounds.top = p_parentBounds.top;
quadrantBounds.left = p_parentBounds.left;
break;
case 3: // SW
quadrantBounds.top = p_parentBounds.height / 2;
quadrantBounds.left = p_parentBounds.left;
break;
case 4: // SE
quadrantBounds.top = p_parentBounds.height / 2;
quadrantBounds.left = p_parentBounds.width / 2;
break;
}
return quadrantBounds;
}
Node& getChildNode(int parentLevel, Box<float> parentBounds, int quadrant) {
static Node temp = Node(parentLevel + 1, getQuadrantBounds(parentBounds, quadrant));
return temp;
}
};
}
Where Box is just a helper class that contains some helper methods for rectangular shapes and collision detection. Any help would be greatly appreciated!

Delete Zero in ArrayList in C++

Inside the ArrayList I'm trying to delete all possible 0's that are appended as input, but for now it only deletes just one 0, no matter where it is located. But seems like I can't delete more than one zero at the time. How can I fix this?
void AList::elimZeros(){
int i;
int curr = 0;
for(i=0; i < listSize; i++) {
if ( (listArray[i] != 0 ) && (curr<listSize) ){
listArray[curr] = listArray[i];
curr++;
}
else if (listArray[i] == 0 )
{
listArray[curr] = listArray[i+1];
listSize--;
curr++;
}
}
}
This is the class for the ADT
class AList : public List {
private:
ListItemType* listArray; // Array holding list elements
static const int DEFAULT_SIZE = 10; // Default size
int maxSize; // Maximum size of list
int listSize; // Current # of list items
int curr; // Position of current element
// Duplicates the size of the array pointed to by listArray
// and update the value of maxSize.
void resize();
public:
// Constructors
// Create a new list object with maximum size "size"
AList(int size = DEFAULT_SIZE) : listSize(0), curr(0) {
maxSize = size;
listArray = new ListItemType[size]; // Create listArray
}
~AList(); // destructor to remove array
This is the input I'm testing with:
int main() {
AList L(10);
AList L2(20);
L.append(10);
expect(L.to_string()=="<|10>");
L.append(20);
expect(L.to_string()=="<|10,20>");
L.append(30);
L.append(0);
L.append(40);
L.append(0);
L.append(0);
expect(L.to_string()=="<|10,20,30,0,40>");
L.elimZeros();
expect(L.to_string()=="<|10,20,30,40>");
assertionReport();
}
It'd be helpful if you posted the class code for AList. Think you confused Java's ArrayList type, but assuming you're using vectors you can always just do:
for (int i = 0; i < listSize; i++) {
if(listArray[i] == 0) listArray.erase(i);
}
EDIT: Assuming this is the template of for the AList class, then there is simply a remove() function. In terms of your code, there are two issues.
You reference listSize in the for loop, then decrement it inside of the loop. Each iteration evaluates the value separately so you're reducing the number of total loop iterations and stopping early.
The other thing is if the entry is zero you shouldn't increment curr and set listArray[curr] = listArray[i+1]. This is basically assuming the next entry will not be a zero. So if it is, then you're copying the element and moving to the next. Your if statement can be cleaned up with:
if (listArray[i] == 0) {
listSize--;
} else {
listArray[curr] = listArray[i];
curr++;
}

Placing the contents of a linked list in an array reference

My instructions are...
// Description: Places the payload contents of the list in the
// array referenced by 'populateMeWithElements'.
// Returns the number of elements that were placed
// in the provided memory location.
// Precondition: Enough memory has been allocated to the provided
// memory location to hold the full contents
// of the list.
// Postcondition: The memory allocated for 'populateMeWithElements'
// has been deallocated after the completion of
// this method call.
int getListElements(int* populateMeWithElements);
I have this written...
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
OOLNode* iterator = this->start;
int* populateMeWithElements = new int[getListSize()];
for (int i = 0; iterator->next != NULL; i++) {
populateMeWithElements[i] = iterator->payload;
iterator = iterator->next;
count++;
}
return count;
}
but I am not sure if it is correct and if it is...
How do I display the contents in my driver
Where I deallocate the memory (do I do this in the driver or in the function that I wrote?)
Thanks in advance for any suggestions or help.
Your function is declaring a local populateMeWithElements variable that shadows the input populateMeWithElements parameter. You are filling the array that you allocate locally, you are not populating the caller's array at all.
For that matter, your function should not be using new[] at all, since the instructions clearly state that the precondition of the function is that the caller has already allocated an array of sufficient size beforehand, and will deallocate that array after the function exits. So, your function's job is merely to fill the caller's array, nothing more.
And on that task, your loop is wrong. iterator->next != NULL needs to be iterator != NULL, otherwise if the list is empty then the 1st access of iterator->next will fail, and if the list is not empty then the payload of the tail node will be skipped.
Try this instead:
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
OOLNode* iterator = this->start;
for (int i = 0; iterator != NULL; i++) {
populateMeWithElements[i] = iterator->payload;
iterator = iterator->next;
++count;
}
return count;
}
OOLList list;
// populate list as needed...
int* elements = new int[list.getListSize()];
int count = list.getListElements(elements);
for(int i = 0; i < count; ++i) {
// use elements[i] as needed...
}
delete[] elements;
The function can be simplified a bit further:
int OOLList::getListElements(int* populateMeWithElements) {
int count = 0;
for (OOLNode* iterator = this->start; iterator != NULL; iterator = iterator->next) {
populateMeWithElements[count++] = iterator->payload;
}
return count;
}
Or even:
int OOLList::getListElements(int* populateMeWithElements) {
int* ptr = populateMeWithElements;
for (OOLNode* iterator = this->start; iterator != NULL; iterator = iterator->next) {
*ptr++ = iterator->payload;
}
return ptr - populateMeWithElements;
}

Need to reference and update value from nested class C++

Bear with me, I'm new to C++. I'm trying to update a value which is stored in a vector, but I'm getting this error:
non-const lvalue reference to type 'Node'
I'm using a simple wrapper around std::vector so I can share methods like contains and others (similar to how the ArrayList is in Java).
#include <vector>
using namespace std;
template <class T> class NewFrames {
public:
// truncated ...
bool contains(T data) {
for(int i = 0; i < this->vec->size(); i++) {
if(this->vec->at(i) == data) {
return true;
}
}
return false;
}
int indexOf(T data) {
for(int i = 0; i < this->vec->size(); i++) {
if(this->vec->at(i) == data) {
return i;
}
}
return -1;
}
T get(int index) {
if(index > this->vec->size()) {
throw std::out_of_range("Cannot get index that exceeds the capacity");
}
return this->vec->at(index);
}
private:
vector<T> *vec;
};
#endif // A2_NEWFRAMES_H
The class which utilizes this wrapper is defined as follows:
#include "Page.h"
#include "NewFrames.h"
class Algo {
private:
typedef struct Node {
unsigned reference:1;
int data;
unsigned long _time;
Node() { }
Node(int data) {
this->data = data;
this->reference = 0;
this->_time = (unsigned long) time(NULL);
}
} Node;
unsigned _faults;
Page page;
NewFrames<Node> *frames;
};
I'm at a point where I need to reference one of the Node objects inside of the vector, but I need to be able to change reference to a different value. From what I've found on SO, I need to do this:
const Node &n = this->frames->get(this->frames->indexOf(data));
I've tried just using:
Node n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
and then viewing the data in the debugger, but the value is not updated when I check later on. Consider this:
const int data = this->page.pages[i];
const bool contains = this->frames->contains(Node(data));
Node node = this->frames->get(index);
for(unsigned i = 0; i < this->page.pages.size(); i++) {
if(node == NULL && !contains) {
// add node
} else if(contains) {
Node n = this->frames->get(this->frames->indexOf(data));
if(n.reference == 0) {
n.reference = 1;
} else {
n.reference = 0;
}
} else {
// do other stuff
}
}
With subsequent passes of the loop, the node with that particular data value is somehow different.
But if I attempt to change n.reference, I'll get an error because const is preventing the object from changing. Is there a way I can get this node so I can change it? I'm coming from the friendly Java world where something like this would work, but I want to know/understand why this doesn't work in C++.
Node n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
This copies the Node from frames and stores the copy as the object n. Modifying the copy does not change the original node.
The simplest "fix" is to use a reference. That means changing the return type of get from T to T&, and changing the previous two lines to
Node& n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
That should get the code to work. But there is so much indirection in the code that there are likely to be other problems that haven't shown up yet. As #nwp said in a comment, using vector<T> instead of vector<T>* will save you many headaches.
And while I'm giving style advice, get rid of those this->s; they're just noise. And simplify the belt-and-suspenders validity checks: when you loop from 0 to vec.size() you don't need to check that the index is okay when you access the element; change vec.at(i) to vec[i]. And in get, note that vec.at(index) will throw an exception if index is out of bounds, so you can either skip the initial range check or keep the check (after fixing it so that it checks the actual range) and, again, use vec[index] instead of vec.at(index).

C++ Lock free producer/consumer queue

I was looking at the sample code for a lock-free queue at:
http://drdobbs.com/high-performance-computing/210604448?pgno=2
(Also reference in many SO questions such as Is there a production ready lock-free queue or hash implementation in C++)
This looks like it should work for a single producer/consumer, although there are a number of typos in the code. I've updated the code to read as shown below, but it's crashing on me. Anybody have suggestions why?
In particular, should divider and last be declared as something like:
atomic<Node *> divider, last; // shared
I don't have a compiler supporting C++0x on this machine, so perhaps that's all I need...
// Implementation from http://drdobbs.com/high-performance-computing/210604448
// Note that the code in that article (10/26/11) is broken.
// The attempted fixed version is below.
template <typename T>
class LockFreeQueue {
private:
struct Node {
Node( T val ) : value(val), next(0) { }
T value;
Node* next;
};
Node *first, // for producer only
*divider, *last; // shared
public:
LockFreeQueue()
{
first = divider = last = new Node(T()); // add dummy separator
}
~LockFreeQueue()
{
while( first != 0 ) // release the list
{
Node* tmp = first;
first = tmp->next;
delete tmp;
}
}
void Produce( const T& t )
{
last->next = new Node(t); // add the new item
last = last->next; // publish it
while (first != divider) // trim unused nodes
{
Node* tmp = first;
first = first->next;
delete tmp;
}
}
bool Consume( T& result )
{
if (divider != last) // if queue is nonempty
{
result = divider->next->value; // C: copy it back
divider = divider->next; // D: publish that we took it
return true; // and report success
}
return false; // else report empty
}
};
I wrote the following code to test this. Main (not shown) just calls TestQ().
#include "LockFreeQueue.h"
const int numThreads = 1;
std::vector<LockFreeQueue<int> > q(numThreads);
void *Solver(void *whichID)
{
int id = (long)whichID;
printf("Thread %d initialized\n", id);
int result = 0;
do {
if (q[id].Consume(result))
{
int y = 0;
for (int x = 0; x < result; x++)
{ y++; }
y = 0;
}
} while (result != -1);
return 0;
}
void TestQ()
{
std::vector<pthread_t> threads;
for (int x = 0; x < numThreads; x++)
{
pthread_t thread;
pthread_create(&thread, NULL, Solver, (void *)x);
threads.push_back(thread);
}
for (int y = 0; y < 1000000; y++)
{
for (unsigned int x = 0; x < threads.size(); x++)
{
q[x].Produce(y);
}
}
for (unsigned int x = 0; x < threads.size(); x++)
{
q[x].Produce(-1);
}
for (unsigned int x = 0; x < threads.size(); x++)
pthread_join(threads[x], 0);
}
Update: It ends up that the crash is being caused by the queue declaration:
std::vector<LockFreeQueue<int> > q(numThreads);
When I change this to be a simple array, it runs fine. (I implemented a version with locks and it was crashing too.) I see that the destructor is being called immediate after the constructor, resulting in doubly-freed memory. But, does anyone know WHY the destructor would be called immediately with a std::vector?
You'll need to make several of the pointers std::atomic, as you note, and you'll need to use compare_exchange_weak in a loop to update them atomically. Otherwise, multiple consumers might consume the same node and multiple producers might corrupt the list.
It's critically important that these writes (just one example from your code) occur in order:
last->next = new Node(t); // add the new item
last = last->next; // publish it
That's not guaranteed by C++ -- the optimizer can rearrange things however it likes, as long as the current thread always acts as-if the program ran exactly the way you wrote it. And then the CPU cache can come along and reorder things further.
You need memory fences. Making the pointers use the atomic type should have that effect.
This could be totally off the mark, but I can't help but wonder whether you're having some sort of static initialization related issue... For laughs, try declaring q as a pointer to a vector of lock-free queues and allocating it on the heap in main().