Functional Code Breaks When Used Twice - c++

I'm still working on my Field class, and tried to improve my piss-poor insertion/erase performance.
However, the new function works once, then breaks catastrophically when I use it a second time.
This is the code:
template <class T>
T *Field<T>::insert(const T *pPos, const T& data)
{
// Special case: field is empty. insert should still succeed.
// Special case: Pointing to one past the end. insert should still succeed
if( empty() || pPos == last() )
{
this->push_back(data);
return (this->last() - 1);
}
/* Explanation: Find cell before which to insert new value. Push_back new
new value, then keep swapping cells until reaching *pPos and swapping it
with data. The while fails, we exit, insert successful. */
T *p = ( std::find( this->first(), this->last(), *pPos ));
if( p != last() )
{
this->push_back(data);
T *right = (this->last() - 1);
T *left = (this->last() - 2);
while( *pPos != data )
std::iter_swap( left--, right-- );
// pPos *has* to be the destination of new value, so we simply return param.
return const_cast<T*>(pPos);
}
else
throw std::range_error("Not found");
}
Calling code from main
// Field already has push_back()ed values 10, 20, 30.
field->insert( &(*field)[2], 25 ); // field is a ptr (no reason, just bad choice)
Produces this output when printed on the console.
Field: 10 20 30 // Original Field
25 // Function return value
Field: 10 20 25 30 // Correct insertion.
New calling code from main
// Field already has push_back()ed values 10, 20, 30
field->insert( &(*field)[2], 25 );
field->insert( &(*field)[3], 35 );
Produces this output when printed on the console.
Field: 10 20 30
25
35
-4.2201...e+37, 10, 15, 20, 30
Windows has triggered a breakpoint in Pg_1.exe.
This may be due to a corruption in the heap (oh shit).
No symbols are loaded for any call stack frame.
The source code cannot be displayed.
The console then proceeds to never shutdown again until I close VSC++08 itself.
What? Why? How? What is my code doing!?
Additional Info
The Field has a size of three before the push, and a capacity of four. After two insertions, the Field is correctly increased to have a capacity of 8 (doubled), and stores five elements.
It doesn't matter where I insert my second element with insert(), it will fail the exact same way. Same output, even same number (I think) at the first cell.
Additional Code
Push_Back()
Note: This code was not changed during my refactoring. This function has always worked, so I highly doubt that this will be the problem-cause.
/* FieldImpl takes care of memory management. it stores the values v_, vused_,
and vsize_. Cells in the Field are only constructed when needed through a
placement new that is done through a helper function. */
template <class T>
void Field<T>::push_back(const T& data)
{
if( impl_.vsize_ == impl_.vused_ )
{
Field temp( (impl_.vsize_ == 0) ? 1
: (impl_.vsize_ * 2) );
while( temp.impl_.vused_ != this->impl_.vused_ )
temp.push_back( this->impl_.v_[temp.size()] );
temp.push_back(data);
impl_.Swap(temp.impl_);
}
else
{
// T *last() const { return &impl_.v_[impl_.vused_]; }
// Returns pointer to one past the last constructed block.
// variant: T *last() const { return impl_.v_; }
Helpers::construct( last(), data );
++impl_.vused_;
}
}

// ...
if( p != last() )
{
this->push_back(data);
After this line pPos may not be a valid pointer anymore.
The console then proceeds to never shutdown again until I close VSC++08 itself.
Tried clicking the Stop button in the debugger?

From the Debugger, and from ybungalobill, it is possible to see that pPos is invalidated after a special case in the
if( p != last()
{
this->push_back(data);
part of the code. If the array is resized, the pointer is invalidated. To bridge this, I simply stored const T pos = *pPos before the push and therefore removed the use of the *pPos pointer after a push.
Updated code:
const T pos = *pPos;
T *p = ( std::find( this->first(), this->last(), pos ) );
if( p != last() )
{
this->push_back(data);
p = ( std::find( this->first(), this->last(), pos ) );
T *right = (this->last() - 1);
T *left = (this->last() - 2);
while( *p != data )
std::iter_swap( left--, right-- );
return const_cast<T*>(p);
}

Related

How can i make this algorithm more memory efficient?

I have been working on this piece of code for a couple of days and it seems
to work just fine for search trees of relative small size, but working with higher ones gives segmentation fault.
I have tried to find the specific place where such error comes from by using printing flags, and it seems to break at the is_goal() function. But the code of that function can be assumed as correct.
So the problems seems to be a memory problem, that's why I have the queue in the heap, and also the Nodes that I am creating. But it still crashes.
Are there any more memory saving tricks that can be taking into account that I am not using? Or maybe there is a better way to save such nodes?
It is important to note that I need to use BFS (I can't use A* to make the search tree smaller).
Also if you need to know, the map is a hash table where I save the coloring of the nodes so I don't have duplicates when exploring (This is because the hash saves depending on the state information and not the Node information).
EDIT: i have been told to indicate the goal to accomplish, such is to find the goal state in the search tree, the goal is to be be able to iterate over
big problems like rubik 3x3x3, n-puzzle 4x4 5x5, tower of hanoi and such.To do so, the memory used has to be minimal since the search tree of such problems are really big, the final objective is to compare this algorithm with others like a*, dfid, ida*, and so on. I hope this is enough information.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> *open = new std::queue<Node*>();
state_map_add( map, &start, 1);
Node* n = new Node(start);
open->push(n);
while( !open->empty() ) {
n = open->front();
state = n->get_state();
open->pop();
if (is_goal(&state) == 1) return n;
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open->push(nchild);
}
}
}
return NULL;
}
I see a number of memory leaks.
open is never deleted but maybe could allocated in the stack instead of in the heap.
std::queue<Node*> open;
More important none of the node you push in the queue are deleted this is probably the origin of very big memory consumption.
Delete the nodes that you remove from the queue and that you don't plan to reuse. Delete the nodes of the queue before your get rid of the queue.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> open;
state_map_add( map, &start, 1);
Node* n = new Node(start);
open.push(n);
while( !open.empty() ) {
n = open.front();
state = n->get_state();
open.pop();
if (is_goal(&state) == 1) {
for (std::queue<Node*>::iterator it = open.begin(); it != open.end(); ++it)
delete *it;
return n;
}
else {
delete n;
}
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open.push(nchild);
}
}
}
return NULL;
}

How can vector const_iterator go past vector end?

I have the following code in an application that threw an access violation exception:
size_t CConnectionsDoc::get_active_connections( std::vector<CString> &conn )
{
CString temp;
size_t cnt = 0;
conn.clear();
if( initialized ) {
for( std::vector<ACTIVE_CONNECTIONS>::const_iterator c_i = connections_vector.begin();
c_i != connections_vector.end(); c_i++ ) {
temp.Format( "%s:%d:%d:%lu", ( LPCTSTR )c_i->their_ip,
c_i->their_port, c_i->our_sd, c_i->their_pa );
conn.push_back( temp );
cnt++;
}
}
return cnt;
}
void CConnectionsDoc::update_connections( const uint sd )
{
std::vector<ACTIVE_CONNECTIONS>::iterator iter = connections_vector.begin();
while( iter != connections_vector.end() ) {
if( iter->our_sd == sd ) {
connections_vector.erase(iter);
break;
}
iter++;
}
}
typedef struct active_connections
{
CString their_ip;
unsigned int their_port;
unsigned int our_sd;
unsigned long their_pa;
} ACTIVE_CONNECTIONS;
example data
their_ip "192.168.1.125"
their_port 60849
our_sd 1096
their_pa 2097260736
This is a Visual Studio 2012 C++ app and from a debugging session using a dump file I found the following values:
initialized=1
connections_vector size=8
connections_vector capacity=13
connections_vector entries 0-7 have valid data and debugger does not show any entries past element 7
cnt=13 at the time of the crash (odd it is the same size of the capacity)
conn size=13
conn capacity=13
std::vector conn has the 8 correct entries from the connections_vector plus 5 entries that look like valid data, but connections_vector.erase(it) was called in another function to remove disconnected entries prior to calling get_active_connections.
It appears that the const_iterator went beyond connections_vector.end() until it tried to access one element beyond the capacity of the connections_vector and crashed, but I don't see how that is possible. Any ideas? Thanks in advance.
You tried to erase some of the objects from the same vector. If you don't use erase remove idiom, data will not be cleaned up from vector. On top of that you did erase operation inside a loop, so iterator is invalidated. Please refer following more details
Iterator invalidation rules
http://en.wikipedia.org/wiki/Erase–remove_idiom

Checking if reducing iterator points to a valid element

I need to know if I can reduce the iterator and have a valid object. The below errors out because I reduce the iterator by 1 which doesn't exist. How can I know that so I don't get the error?
ticks.push_front(Tick(Vec3(0, 0, 5), 0));
ticks.push_front(Tick(Vec3(0, 0, 8), 100));
ticks.push_front(Tick(Vec3(0, 0, 10), 200));
bool found = false;
list<Tick, allocator<Tick>>::iterator iter;
for (iter = ticks.begin(); iter != ticks.end(); ++iter)
{
Tick t = (*iter);
if (214>= t.timestamp)
{
prior = t;
if (--iter != ticks.end())
{
next = (*--iter);
found = true;
break;
}
}
}
I'm trying to find the entries directly "above" and directly "below" the value 214 in the list. If only 1 exists then I don't care. I need above and below to exist.
After your edits to the question, I think I can write a better answer than what I had before.
First, write a comparison function for Ticks that uses their timestamps:
bool CompareTicks(const Tick& l, const Tick& r)
{
return l.timestamp < r.timestamp;
}
Now use the function with std::upper_bound:
// Get an iterator pointing to the first element in ticks that is > 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itAbove = std::upper_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);
if(itAbove == ticks.end())
; // there is nothing in ticks > 214. I don't know what you want to do in this case.
This will give you the first element in ticks that is > 214. Next, you can use lower_bound to find the first element that is >= 214:
// get an iterator pointing to the first element in ticks that is >= 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itBelow = std::lower_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);
You have to do one extra step with itBelow now to get the first element before 214, taking care not to go past the beginning of the list:
if(itBelow == ticks.begin())
; // there is nothing in ticks < 214. I don't know what you want to do in this case.
else
--itBelow;
Now, assuming you didn't hit any of the error cases, itAbove is pointing to the first element > 214, and itBelow is pointing to the last element < 214.
This assumes your Ticks are in order by timestamp, which seems to be the case. Note also that this technique will work even if there are multiple 214s in the list. Finally, you said the list is short so it's not really worth worrying about time complexity, but this technique could get you logarithmic performance if you also replaced the list with a vector, as opposed to linear for iterative approaches.
The answer to your core question is simple. Don't increment if you are at the end. Don't decrement if you are at the start.
Before incrementing, check.
if ( iter == ticks.end() )
Before decrementig, check.
if ( iter == ticks.begin() )
Your particular example
Looking at what you are trying to accomplish, I suspect you meant to use:
if (iter != ticks.begin())
instead of
if (--iter != ticks.end())
Update
It seems you are relying on the contents of your list being sorted by timestamp.
After your comment, I think what you need is:
if (214>= t.timestamp)
{
prior = t;
if (++iter != ticks.end())
{
next = *iter;
if ( 214 <= next.timestep )
{
found = true;
break;
}
}
}
Update 2
I agree with the comment made by #crashmstr. Your logic can be:
if (214 <= t.timestamp)
{
next = t;
if ( iter != ticks.begin())
{
prior = *--(iter);
found = true;
break;
}
}
I think you can do what you want with std::adjacent_find from the standard library <algorithm>. By default std::adjacent_find looks for two consecutive identical elements but you can provide your own function to define the relationship you are interested in.
Here's a simplified example:
#include <algorithm>
#include <iostream>
#include <list>
struct matcher
{
matcher(int value) : target(value) {}
bool operator()(int lo, int hi) const {
return (lo < target) && (target < hi);
}
int target;
};
int main()
{
std::list<int> ticks = { 0, 100, 200, 300 };
auto it = std::adjacent_find(ticks.begin(), ticks.end(), matcher(214));
if (it != ticks.end()) {
std::cout << *it << ' ' << *std::next(it) << '\n';
} else {
std::cout << "not found\n";
}
}
This outputs 200 300, the two "surrounding" values it found.

Delete and add elements to vector inside main loop

I searched before but couldn't find any answers. I am somewhat new to c++, so hopefully this question won't be too stupid.
I am trying to add and remove elements in a vector, in my case populated with particles during a big update or drawing loop over all particles. For example remove some particles because they died, but also add a few other ones because one particle collided with an object and I want to show a small particle burst at the point of collision. I made this simple test code in a demo file to get to the bottom of the problem.
I think the problem is since I delete and add particles the iterator pointer becomes invalid. Deletion works, but when I add a few random ones I get a null pointer. the code below is somewhat verbose, I know I should use iterators with begin() and end() but I had the same problem with those, and played with the code a bit, trying more javascript array style looping because I am more familiar with that.
void testApp::drawParticles()
{
int i=0;
int max = particles.size();
vector<Particle*>::iterator it = particles.begin();
while ( i < max ) {
Particle * p = particles[i];
if ( ofRandom(1) > .9 ) {
it = particles.erase(it);
max = particles.size();
} else {
ofSetColor(255, 255, 0);
ofCircle( p->x, p->y, p->z, 10);
if ( ofRandom(1) < .1 ) addSomeNewOnes();
i++;
it++;
}
}
}
void testApp::addSomeNewOnes()
{
int max = ofRandom(4);
for ( int i=0; i<max; i++ ) {
Particle * p = new Particle();
p->x = ofRandom( -ofGetWidth()/2, ofGetWidth()/2 );
p->y = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
p->z = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
particles.push_back( p );
}
}
Every time you insert in to a vector, the iterators to it are potentially invalidated. You cannot do this:
if ( ofRandom(1) < .1 ) addSomeNewOnes();
it++
Because after the call to addSomeNewOnes(), it is invalid.
You can use the iterator returned by a call to vector::insert, but in your case that would mean re-engineering your code.
This is something you might want to do, anyway, as your code is a bit kludgy.
You could loop at it from the end, which should allow you to delete your current (since you're only deleting off of the end) and add new ones which get added to the end:
Vector<Particle*>::iterator it = particles.end();
while (iter != particles.begin()) {
Particle * p = *iter;
if ( ofRandom(1) > .9 ) {
particles.erase(iter);
} else {
ofSetColor(255, 255, 0);
ofCircle( p->x, p->y, p->z, 10);
if ( ofRandom(1) < .1 ) addSomeNewOnes();
}
iter--;
}
If you are not adding, based on the info here, iterators in STL are stable so you should be able to iterate forwards and still be able to achieve the same result.
Iterators are invalidated in some cases when the underlying data changes.
You'll have to break out of the loop and start again.
You should be able to do that by wrapping your whole drawParticles function in a while(notDone) loop, and setting notDone to true when you're done modifying the vector.
Here's another SO question with the rules: Iterator invalidation rules
it = particles.erase(it);
will return an iterator pointing to the new location of the element following the one erased. If the one erased happens to be the last one, it will point to particles.end(). it++ on "end" is an error.
Also, if:
if ( ofRandom(1) < .1 ) addSomeNewOnes();
evaluates to true and addSomeNewOnes() is called, as others have said, that will also invalidate the iterator.
Are you inserting and deleting at the location of the iterator? If so,
insert and erase return iterators which will be valid, and you can use
those. Something like:
std::vector<T>::iterator i = v.begin();
while ( i != v.end() ) {
if ( someCondition ) {
i = v.erase( i );
} else {
++ i;
}
}
is a more or less standard idiom.
For random insertions and deletions, you have to work with indexs, which
you update according to the number of elements inserted or deleted, and
whether the insertion or deletion was in front of or behind the current
position.
There's an easy way to make this work correctly without worrying about invalidation rules: just build a new vector for the next iteration.
typedef vector<Particle*> ParticleVector;
// modifies the particle vector passed in
void testApp::drawParticles(ParticleVector &particles)
{
ParticleVector next;
next.reserve(particles.size()); // seems like a reasonable guess
for (auto it = particles.begin(); it != particles.end(); ++it)
{
Particle *p = *it;
if (ofRandom(1) > .9) {
// don't copy to the next cycle
delete p;
} else {
// copy to the next cycle
next.push_back(p);
ofSetColor(255, 255, 0);
ofCircle(p->x, p->y, p->z, 10);
if (ofRandom(1) < .1)
addSomeNewOnesTo(next);
}
}
particles.swap(next);
}
Note how much easier it is to refactor like this when you're not using globals, btw.
void testApp::addSomeNewOnesTo(ParticleVector &particles)
{
int max = ofRandom(4);
for ( int i=0; i<max; i++ ) {
Particle * p = new Particle();
p->x = ofRandom( -ofGetWidth()/2, ofGetWidth()/2 );
p->y = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
p->z = ofRandom( -ofGetHeight()/2, ofGetHeight()/2 );
particles.push_back( p );
}
}
On another note : Isn't there a memory leak in your implementation?
You are using
vector<Particle*> particles
and also using particles.erase().
Wont that just delete your pointer to Particle,and not created object?

hashkey collision when removing C++

To make the search foreach "symbol" i want to remove from my hashTable, i have chosen to generate the hashkey i inserted it at. However, the problem that Im seeing in my remove function is when I need to remove a symbol from where a collision was found it previously results in my while loop condition testing false where i do not want.
bool hashmap::get(char const * const symbol, stock& s) const
{
int hash = this->hashStr( symbol );
while ( hashTable[hash].m_symbol != NULL )
{ // try to find a match for the stock associated with the symbol.
if ( strcmp( hashTable[hash].m_symbol , symbol ) == 0 )
{
s = &hashTable[hash];
return true;
}
++hash %= maxSize;
}
return false;
}
bool hashmap::put(const stock& s, int& usedIndex, int& hashIndex, int& symbolHash)
{
hashIndex = this->hashStr( s.m_symbol ); // Get remainder, Insert at that index.
symbolHash = (int&)s.m_symbol;
usedIndex = hashIndex;
while ( hashTable[hashIndex].m_symbol != NULL ) // collision found
{
++usedIndex %= maxSize; // if necessary wrap index around
if ( hashTable[usedIndex].m_symbol == NULL )
{
hashTable[usedIndex] = s;
return true;
}
else if ( strcmp( hashTable[usedIndex].m_symbol , s.m_symbol ) == 0 )
{
return false; // prevent duplicate entry
}
}
hashTable[hashIndex] = s; // insert if no collision
return true;
}
// What if I need to remove an index i generate?
bool hashmap::remove(char const * const symbol)
{
int hashVal = this->hashStr( symbol );
while ( hashTable[hashVal].m_symbol != NULL )
{
if ( strcmp( hashTable[hashVal].m_symbol, symbol ) == 0 )
{
stock temp = hashTable[hashVal]; // we cansave it
hashTable[hashVal].m_symbol = NULL;
return true;
}
++hashVal %= maxSize; // wrap around if needed
} // go to the next cell meaning their was a previous collision
return false;
}
int hashmap::hashStr(char const * const str)
{
size_t length = strlen( str );
int hash = 0;
for ( unsigned i = 0; i < length; i++ )
{
hash = 31 * hash + str[i];
}
return hash % maxSize;
}
What would I need to do to remove a "symbol" from my hashTable from a previous collision?
I am hoping it is not java's equation directly above.
It looks like you are implementing a hash table with open addressing, is that right? Deleting is a little tricky in that scheme. See http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf:
"Deletion of keys is problematic with open addressing: If there are two colliding keys x and y with h(x) = h(y), and key x is inserted before key y, and one wants to delete key x, this cannot simply be done by marking T[h(x)] as FREE, since then y would no longer be found. One possibility would be to mark T[h(x)] as DELETED (another special entry), which is skipped when searching for a key. A table place marked as DELETED may also be re-used for storing another key z that one wants to insert if one is sure that this key z is not already in the table (i.e., by reaching the end of the probe sequence for key z and not finding it). Such re-use complicates the insertion method. Moreover, places with DELETED keys fill the table."
What you need to do is create a dummy sentinel value that represents a "deleted" item. When you insert a new value into the table, you need to check to see if an element is NULL or "deleted". If a slot contains this sentinel "deleted" value or the slot is NULL, then the slot is a valid slot for insertion.
That said, if you are writing this code for production, you should consider using the boost::unordered_map, instead of rolling your own hash map implementation. If this is for schoolwork,... well, good luck.