vector std::out_of_range error

Hi,

I am having a std::out_of_range error message when I try to delete objects from a vector container, I create 10 objects of type Boid in a Flock class, when the user clicks in one of them I want to delete the Boid.

Here is my code:

  
  
#include "Flock.h"  
  
Flock::Flock() {  
	// create boids  
	boidCount = 0;  
	for (int i = 0; i < NUM_BOIDS; i++) {  
		addBoid(ofxVec2f(ofGetWidth() * 0.5f, ofGetHeight() * 0.5f));  
	}  
}  
  
void Flock::run() {  
	for (vector <Boid*>::iterator it = boids.begin(); it != boids.end();) {  
		(*it)->run(boids);  
		if ((*it)->dead) {  
			delete *it;  
			it = boids.erase(it);  
		}  
		else ++it;  
	}  
}  
  
void Flock::display() {  
	for (unsigned i = 0; i < boids.size(); i++) {  
		Boid* boid = boids.at(i);  
		boid->display();  
	}  
}  
  
void Flock::addBoid(ofxVec2f location) {  
	float maxSpeed = 1.5f; //ofRandom(2.0f, 3.0f);  
	float maxForce = 0.05f; //ofRandom(0.05f, 0.1f);  
	  
	boids.push_back(new Boid(boidCount, location, maxSpeed, maxForce));  
	  
	boidCount++;  
}  
  
void Flock::killBoid(int idToKill) {  
	Boid* boid = boids.at(idToKill);  
	boid->dead = true;  
	  
	//cout << "boid killed: " << idToKill << endl;  
}  
  

This error is very random, some times I get it when I delete 3 boids, some time when I delete 9, but I never manage to delete all of them.

This is what I get:

terminate called after throwing an instance of ‘std::out_of_range’
what(): vector::_M_range_check

Program received signal: “SIGABRT”.
sharedlibrary apply-load-rules all
warning: Could not find object file “/Users/theo/Documents/CODE/__OPENFRAMEWORKS/SANDBOX/COMPILE_LIBRARIES/buildGlutFramework/libForeground.a(macx_foreground.o)” - no debug information available for “/Users/mcast/Code/GLUT-ToPost/macx_foreground.m”.

warning: Could not find object file “/Developer/usr/lib/gcc/i686-apple-darwin9/4.0.1/libgcc.a(_eprintf.o)” - no debug information available for “/var/tmp/gcc/gcc-5493~1/src/gcc/libgcc2.c”.

kill
quit

The Debugger has exited with status 0.(gdb)

Any ideas will be much appreciated

Cheers
rS

Hi,
I suspect the argument to killBoid might in some cases be bigger than the size of your vector.

Typically, if you pass the id of a boid to killBoid, there might be a mismatch between the id and the position of the boid in the vector, especially if you have already removed an element.

hope this helps

regards

david

this:

  
for (vector <Boid*>::iterator it = boids.begin(); it != boids.end();) {  
      (*it)->run(boids);  
      if ((*it)->dead) {  
         delete *it;  
         it = boids.erase(it);  
      }  
      else ++it;  
   }  

is making the iterator invalid each time you erase a position.

also a vector is not a good structure to add and remove things in the middle very often. better to use a list, then it will be something like:

  
  
list<list<Boid*>::iterator> toDelete;  
for (list <Boid*>::iterator it = boids.begin(); it != boids.end();it++) {  
      (*it)->run(boids);  
      if ((*it)->dead) {  
         delete *it;  
         toDelete.push_back(it);  
      }  
   }  
list<list<Boid*>::iterator>::iterator del_it;  
for(del_it=toDelete.begin(),del_it!=toDelete.end();del_it++){  
     boids.erase(*del_it);  
}  

@david The killBoid refereces are fine at the moment of the call

@arturo, I change my code to handle list containers, but now I get errors because I use the vector .at() reference, any idea how I can change this to work with a list?

  
  
void Flock::killBoid(int idToKill) {  
	Boid* boid = boids.at(idToKill);  
	boid->dead = true;  
	  
	//cout << "boid killed: " << idToKill << endl;  
}  
  

Cheers
rS

[quote author=“arturo”]this:

  
for (vector <Boid*>::iterator it = boids.begin(); it != boids.end();) {  
      (*it)->run(boids);  
      if ((*it)->dead) {  
         delete *it;  
         it = boids.erase(it);  
      }  
      else ++it;  
   }  

is making the iterator invalid each time you erase a position.[/quote]

sorry to intercept here. The code above is correct, as erase returns a valid iterator pointing to the next valid element. See http://www.cplusplus.com/reference/stl/vector/erase/

But you are right, a std::list might be better suited.

@ardove: without seeing the rest of the code there’s no much help we can offer. I think the problem lies elsewhere in your code.

Cheers,
Stephan

you cannot access to a position in a list. because of how it’s structured that will mean having to go all over it to access each position. in case you just need to go through it from beginning to end every time, you need to use iterators. if not then you will need to use a vector

Thanks guys for the support, really appreciated

I attach the source code, and here is a bit of explanation

testApp calls Flock, and Flock creates a bunch of Boids, if you click on a Boid I want to delete it, and thats about it

It sort of works, because I get the above error at random points, David mention that the id may be different from the Boid I try to eliminate but I test that and seems to be fine, unless I am missing something

Hope that makes sense

Cheers
rS

src.zip

It sort of works, because I get the above error at random points

Problem 1: In testApp::list_hits() you get undefined values for k if it isn’t set in the loop. Try initializing the variable (say to max unsigned) and checking its value before calling killBoid().

Using uninitialized variables is generally not a good idea and often leads to such “random” errors as you are experiencing.

But even having fixed that I got a call killBoid(8) on a boid-vector of size 8. So there’s something else going wrong with k.

Hi,

i think I was right in suspecting killBoid.

the following change works for me

  
  
void Flock::killBoid(int idToKill) {  
  
    Boid* boid;  
  
    for (int i = 0; i < boids.size(); i++)  
    {  
        boid = boids[i];  
  
        if (boid->id == idToKill)  
            boid->dead = true;  
    }  
  
}  
  

Also, I have the feeling that you are overcomplicating the picking process. I would try to roll my own function relying on mouse positions. Since you are in 2d, a more simple approach should work just fine.

regards

david

Sinasonic and David thanks a lot for the support, it is working, I initialise the variables and replace the code, so far no problems at all

David regarding the code I use for selecting the boids yes you are right it may be to much for my requirements, I just wanted to try how OpenGL picking works, I think I am trying too much stuff at the same time :stuck_out_tongue:

This code I put it together from different posts trying to figure out how to work with pointers, nowis there any way I can check that the code is working as it should, I mean how I can tell for sure that the pointers logic is right?, one way is so far no it doesn’t crash but is there any other way to tell?

I am new to this kind of programming so spare with me

Cheers
rS

@David I replace the entire glSelect method code to this

  
  
void testApp::select(int x, int y) {  
	cout << "touch location(x, y): " << x << ", " << y << endl;  
	  
	ofxVec2f location(x, y);  
	  
	for (int i = 0; i < flock.boids.size(); i++) {  
		ofxVec2f diff(location - flock.boids[i]->location);  
		float d = diff.length();  
		if (d < 30.0f) flock.killBoid(flock.boids[i]->id);  
	}  
}  
  

For 2 reasons:
1- I need to port this to the iPhone, so most of the glSelect openGL methods didnt work on openGL ES
2- Like you said its only in 2D so there is no need for all that extra work

So know I only check how many boids are inside the radius (this case 30.0f) and select then

Cheers
rS

Hey guys,

I have the same problem:
The compiler gives me the following notification after running:
terminate called after throwing an instance of ‘std::out_of_range’
what(): vector::_M_range_check

This is my code, it would be nice, if someone could help me.

cRawSensorData **ppData;
pMediaSample->Lock((const tVoid **)&ppData);
cRawSensorData* pRawSensorData = *ppData;
tUInt8 ui8DeltaPhi=GetPropertyInt(“Angular Increment”); //angular increment 1°
//We need an array with the known raypoints and information if a rayline is occupied with raypoints --> declare a vector of vectors of floats named raypoints
vector<vector > Raypoints; // right now empty
QHash<int,double> point;
vector<vector > Layer;
for(tUInt16 ui16Phi=0; ui16Phi<360; ui16Phi+=ui8DeltaPhi)
{
Raypoints.push_back(vector()); // Add an empty row
Layer.push_back(vector()); // Add an empty row
}
for(tUInt16 ui16Phi=0; ui16Phi<360; ui16Phi+=ui8DeltaPhi)
{
for(tUInt8 ui8Layer=0; ui8Layer<64; ++ui8Layer ){
tUInt32 ui32Index;
pRawSensorData->getIndex(ui32Index,ui8Layer,ui16Phi, 0);
point = pRawSensorData->m_vScan[ui32Index];
if(point.contains(propDist)){
Raypoints.at(ui16Phi).push_back(point[propDist]); // Add column to all rows
Layer.at(ui16Phi).push_back(ui8Layer); // Add column to all rows
}
}
}

vector<CvKalman*>pKalman; //Pointer with data type CvKalman, necessary for the creation of Kalman filters
vector<vector > LifeFilter;
vector<vector >Line; //Line Vector of vectors, all r-values are saved, index is both the line-number and the number of points within the line
//Kalman equations:
//x_k = F*x_k -1 + B*u_k + w_k
//z_k = H_k*x_k + v_k
//w_k and v_k are respectively Gaussian distributions with:
//w_k ~ N(0,Q_k)
//v_k ~ N(0,R_k)
//Initialize Kalman parameters --> Assumption: These parameters are time invariant
const int F[] = { 1, ui8DeltaPhi, 0, 1 }; //Transition matrix F
CvMat* pH = cvCreateMat( 1, 2, CV_32FC1 );
cvSetIdentity( pH, cvRealScalar(1) ); //The measurement matrix is H=[1,0]
//HDL64-E_Velodyne_Laser: We know R_k=sigma^2 of Velodyne
//From the manual: sigma=2cm=0.02m --> variance=sigma^2=0.02^2=R_k
CvMat* pRk = cvCreateMat( 1, 1, CV_32FC1 );
cvSetIdentity( pRk, cvRealScalar(GetPropertyFloat(“Variance Noise Velodyne”)) );
CvMat* pQk = cvCreateMat( 2, 2, CV_32FC1 ); //Process noise covarinace Q_k
cvSetIdentity( pQk, cvRealScalar(GetPropertyFloat(“Process Noise Covariance”)) );
//Variable in order to be able to count the “Filter amount”
tUInt32 ui32Enumerate = 0;
for(tUInt16 ui16Phi=0; ui16Phi<360; ui16Phi+=ui8DeltaPhi){
tUInt16 ui16RayNo = ui16Phi/ui8DeltaPhi+1; //Ray Number
vector<vector > Prediction(2, vector()); //Prediction matrix
vector<vector > PCov(2, vector()); //Prior Error Covariance matrix
CvMat* pChiThreshold = cvCreateMat( 1, 1, CV_32FC1 ); //Threshold for Mahalanobis distance
tFloat32 f32L = GetPropertyFloat(“Initial Value L for P”); // Necessary for Matrix P_k in the initial state

if( ( !( Raypoints.at(ui16Phi).empty() ) ) || ( Raypoints.at(ui16Phi).size() )>0 ){
//if( ui16RayNo > 0 ){
// LifeFilter.at(ui16RayNo).clear(); //Usually this row will be empty, just used for unforseeable/unpredictable occurrences
//}

if( ( (ui16RayNo-1) >= 0 ) && (!pKalman.empty() ) && ( !LifeFilter.at(ui16RayNo-1).empty()) ){
for(tUInt32 ui32Count=0; ui32Count < LifeFilter.at(ui16RayNo-1).size(); ++ui32Count){
//Prediction step of the state vector, NULL because no control matrix, xk’=Fxk-1+B*uk-1 with B=0
memcpy( (pKalman.at(LifeFilter.at(ui16RayNo-1).at(ui32Count)))->transition_matrix->data.fl, F, sizeof(F));
memcpy( (pKalman.at(LifeFilter.at(ui16RayNo-1).at(ui32Count)))->process_noise_cov->data.fl, pQk, sizeof(pQk));
//Kalman Prediction step, the (prior) state vector pointer is returned via function
cvKalmanPredict( (pKalman.at(LifeFilter.at(ui16RayNo-1).at(ui32Count) )), NULL);
//Auxiliary pointers to matrices are named pM1 - pM2 - … and so on
CvMat* pM1 = cvCreateMat( 2, 2, CV_32FC1 );
pM1 = ( (pKalman.at(LifeFilter.at(ui16RayNo-1).at(ui32Count)))->state_pre );
if( ui32Count == LifeFilter.at(ui16RayNo-1).size()-1){
Prediction.at(0).clear();
Prediction.at(1).clear();
PCov.at(0).clear();
PCov.at(1).clear();
}
Prediction.at(0).push_back( cvmGet( pM1, 0, 0 ) );
Prediction.at(1).push_back( cvmGet( pM1, 1, 0 ) );
//Compute value prior error covariance
CvMat* pM2 = cvCreateMat( 2, 2, CV_32FC1 );
pM2 = ( (pKalman.at(LifeFilter.at(ui16RayNo-1).at(ui32Count)))->error_cov_pre );
PCov.at(0).push_back( cvmGet( pM2, 0, 0 ) );
PCov.at(0).push_back( cvmGet( pM2, 0, 1 ) );
PCov.at(1).push_back( cvmGet( pM2, 1, 0 ) );
PCov.at(1).push_back( cvmGet( pM2, 1, 1 ) );
}
}
for(tUInt32 ui32=0; ui32 < Raypoints.at(ui16Phi).size(); ++ui32 ){
if( pKalman.empty() ){
tFloat64 f64R0 = Raypoints.at(ui16Phi).at(ui32);
//Creation of Kalman Filter
//cvCreateKalman(int dynam_params, int measure_params, int control_params) with
//dynam_params - dimensionality of the state vector
//measure_params - dimensionality of the measurement vector
//control_params - dimensionality of the control vector
pKalman.push_back( cvCreateKalman(2,1,0) ); //first pKalman pointer is created
cvSetIdentity( pKalman.at(0)->state_post, cvRealScalar(f64R0) );
cvSetIdentity( pKalman.at(0)->state_pre, cvRealScalar(0));
//Initial Post Covarinace Matrix
CvMat* P = cvCreateMat(2,2,CV_32FC1);
cvZero( P );
cvmSet( P, 0, 0, f32L );
cvmSet( P, 0, 1, 0 );
cvmSet( P, 1, 0, 0 );
cvmSet( P, 1, 1, f32L );
memcpy( pKalman.at(0)->error_cov_post->data.fl, P, sizeof§);
Line.at(0).push_back(f64R0);
continue;
}
//Filter has to be updated --> Computation of Mahalanobis distance is possible
//Determine the measurement residual v_k=z_k-H_k*x_k(-)=z_k-H*x_k(-) within the upcoming for-loop
CvMat *pV = cvCreateMat( 1, 2, CV_32FC1 );
cvZero( pV );
cvmSet( pV, 0, 0, -1 );
cvmSet( pV, 0, 1, 0 ); //pV has the same matrix structure as -H=[-1 0]=-H_k
tFloat32 f32MinValue = 10^10; //very large, unreachable distance as start Mahalanobis distance --> compute Minimum
tUInt32 ui32LineValue;
if( !( pKalman.size() ) ){
ui32LineValue = 0;
}
if( LifeFilter.at(ui16RayNo-1).empty() ){
ui32LineValue = 0;
}
for(tUInt32 ui32Temp=0; ui32Temp < LifeFilter.at(ui16RayNo-1).size(); ++ui32Temp ){
CvMat *pMeasurement = cvCreateMat( 1, 1, CV_64FC1 );
cvZero( pMeasurement );
cvmSet( pMeasurement, 0, 0, Raypoints.at(ui16Phi).at(ui32) );
CvMat* pM3 = cvCreateMat(2, 1 ,CV_32FC1);
cvmSet( pM3, 0 , ui32Temp , Prediction.at(0).at(ui32Temp) );
cvmSet( pM3, 1 , ui32Temp , Prediction.at(1).at(ui32Temp) );
cvMatMulAdd(pV, pM3 , pMeasurement, pV );
//pV is now a pointer to the measurement residual v_k --> required for Mahalanobis distance
//Determine the measurement prediction covariance S_k=H_k*P_k(-)*H_k(T)+R_k
tUInt32 ui32Var = 2*ui32Temp; // after every 2nd column of PCov new raypoint --> variaböe ui32Var is used to describe this feature
tUInt32 ui32Var1 = 2*ui32Temp+1;
CvMat* pM4 = cvCreateMat( 2, 2, CV_32FC1 );
cvmSet( pM4, 0 , ui32Temp , PCov.at(0).at(ui32Var) );
cvmSet( pM4, 0 , ui32Temp , PCov.at(0).at(ui32Var1) );
cvmSet( pM4, 1 , ui32Temp , PCov.at(1).at(ui32Var) );
cvmSet( pM4, 1 , ui32Temp , PCov.at(1).at(ui32Var1) );
CvMat* pM5 = cvCreateMat( 1, 2, CV_32FC1 );
cvMatMul( pH , pM4, pM5); //Compute H_k*P_k(-)
CvMat* pM6 = cvCreateMat( 2, 1, CV_32FC1 );
cvTranspose(pH, pM6 ); //Compute H_k(T) --> Tranpose H_k
CvMat* pS = cvCreateMat( 1, 1, CV_32FC1); //pointer to prediction covarinace S_k
cvMatMulAdd(pM5, pM6 , pRk, pS );
//Determine the Mahalanobis distance (see Bachelor thesis)
//v_k(T)*S_k(-1)*v_k
//Transposed matrix v_k(T): v_k(T)=v_k (because 1x1 matrix)
CvMat* pM7 = cvCreateMat( 1, 1, CV_32FC1);
cvTranspose( pV, pM7 );
CvMat* pM8 = cvCreateMat( 1, 1, CV_32FC1);
cvInvert( pS, pM8 );
CvMat* pM9 = cvCreateMat( 1, 1, CV_32FC1 );
cvMatMul( pM7, pM8, pM9); //pM9: pointer to the matrix product v_k(T)*S_k(-1) with S_k(-1)=1/S_k
CvMat* pMDist = cvCreateMat( 1, 1, CV_32FC1);
cvMatMul( pM9, pV , pMDist); //pMDist: pointer to the Mahalanobis distance v_k(T)*S_k(-1)*v_k
//if-construction --> necessary for the minimum distance
if( f32MinValue > *(pMDist->data.fl) ){
f32MinValue = *(pMDist->data.fl);
ui32LineValue = LifeFilter.at(ui16RayNo-1).at(ui32Temp);
}
}
cvZero( pChiThreshold );
cvmSet( pChiThreshold, 0, 0, GetPropertyFloat(“Threshhold K based on Chi-squared Distribution”) );
//if instruction for Chi-Squared test
//Mahalanobis distance is greater than determined Threshold --> Breakpoint*/
if( ( f32MinValue > *(pChiThreshold->data.fl) ) || ( ui32LineValue == 0) ){
//New Filter necessary --> generate a new one
ui32Enumerate = pKalman.size();
pKalman.push_back( cvCreateKalman(2,1,0) ); // Creation of a new filter
//Initial Post Covarinace Matrix
CvMat* P = cvCreateMat(2,2,CV_32FC1);
cvZero( P );
cvmSet( P, 0, 0, f32L );
cvmSet( P, 0, 1, 0 );
cvmSet( P, 1, 0, 0 );
cvmSet( P, 1, 1, f32L );
memcpy( pKalman.at(ui32Enumerate)->error_cov_post->data.fl, P, sizeof§);

tFloat64 f64R0 = Raypoints.at(ui16Phi).at(ui32);
//Initial Value R0 for the specific angle ui16Phi --> not the same as the initial state component at angle 0
cvSetIdentity( pKalman.at(ui32Enumerate)->state_post, cvRealScalar(f64R0) );
cvSetIdentity( pKalman.at(ui32Enumerate)->state_pre, cvRealScalar(0));
Line.push_back(vector()); // Add an empty row
tFloat64 f64 = Raypoints.at(ui16Phi).at(ui32);
Line.at(ui16Phi).push_back(f64);
LifeFilter.at(ui16RayNo).push_back(ui32Enumerate);
if(ui32 == Raypoints.at(ui16Phi).size()-1){
LifeFilter.push_back(vector()); // Add an empty row
}
}
else{ //No Breakpoint was found --> update Kalman Filter
//Prediction step of the state vector, NULL because no control matrix, xk’=Fxk-1+B*uk-1 with B=0
memcpy( (pKalman.at(ui32LineValue))->transition_matrix->data.fl, F, sizeof(F));
memcpy( (pKalman.at(ui32LineValue))->process_noise_cov->data.fl, pQk , sizeof(pQk));
//Kalman Prediction step, the (prior) state vector pointer is returned via function
cvKalmanPredict( (pKalman.at(ui32LineValue)), NULL);
CvMat* pM10 = cvCreateMat( 2, 2, CV_32FC1 );
pM10 = ( (pKalman.at(ui32LineValue))->state_pre );
CvMat *pMeasurementUpdate = cvCreateMat( 1, 1, CV_64FC1 );
cvZero( pMeasurementUpdate );
cvmSet( pMeasurementUpdate, 0, 0, Raypoints[ui16Phi][ui32] );
cvKalmanCorrect(pKalman.at(ui32LineValue), pMeasurementUpdate); //Function returns updated pKalman->state post
LifeFilter.at(ui16RayNo).push_back(ui32LineValue);
Line.at(ui32LineValue).push_back( Raypoints.at(ui16Phi).at(ui32) );
if(ui32 == Raypoints.at(ui16Phi).size()-1){
LifeFilter.push_back(vector()); // Add an empty row
}
}
}
}
}

I am using OpenCV for the realization of a Kalman Filter. Please help me, its very important.

Thanks a lot.

50jab