CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Sep 2011
    Posts
    8

    Unhappy C++ vector length error at run time

    Hi,

    I'm having a problem with vectors, its the first time i'm using this structure so i'm probably missing something obvious.

    What i'm trying to do is, create a class with a vector as a member, my code compiles with no errors but 4 warnings ... also to do with another vector.

    the code compiles, but when debugging there is an error: vector<T> too long... also it says std::length_error at memory location 0x0030f1d8..

    Just to explain my code, i'm trying to implement a bfs search for the 8 puzzle problem. I feel logically my code is correct and so i have not posted everything. Also it is a lot to read, but i have posted all the bits concerning the vectors.

    I would appreciate any help!! thanks in advance!

    here is my code:

    my header file:
    Code:
    #ifndef HEADER_H
    #define HEADER_H
    
    #include <vector>
    using std::vector;
    class node{
    
    public:
    		int state[3][3];
    		int id;
    		char action;
    		vector<int> list;
    		node* parent;
    		node();
    		~node();
    };
    
    
    #endif
    file with definitions:
    Code:
    #include "header.h"
    #include <iostream>
    
    node::node() { list.reserve(10); }
    node::~node() { }
    and the main file
    Code:
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include "header.h"
    
    int choice;
    int i,j,x,y,a,b,c,d,aa, children, start, stop, child;
    int InState [3][3];
    int GoalState [3][3];
    bool leave = false;
    char moves[4];
    std::vector<int> final;
    
    using namespace std;
    int main(){
    
    
    	GoalState[0][0] = 1;
    	GoalState[0][1] = 2;
    	GoalState[0][2] = 3;
    	GoalState[1][0] = 8;
    	GoalState[1][1] = 0;
    	GoalState[1][2] = 4;
    	GoalState[2][0] = 7;
    	GoalState[2][1] = 6;
    	GoalState[2][2] = 5;
    
    	cout<<"Welcome to the 8-puzzle"<<endl;
    		
    	cout<<"Our goal state is :"<<endl;
    	cout<<endl;
    	for (i=0; i<3; i++){
    		cout<<GoalState[i][0]<<" "<<GoalState[i][1]<<" "<<GoalState[i][2]<<endl;
    	}
    
    
    	cout<<"\nEnter Initial State one integer at a time:"<<endl;
    	cout<<"Please use integers 0 to 8 only where 0 represents the blank tile"<<endl;
    	
    	for (i = 0; i<3; i++) { 
    		for (j=0; j<3; j++){
    			cin>> InState[i][j];
    			if (InState[i][j] > 8) {
    				cout<<"number should be from 0 to 8. Re-enter"<<endl;
    				cin>> InState[i][j];}
    
    		}
    	}
    
    	//at this point we find the position of zero or the blank
    	for (i = 0; i<3; i++) { 
    		for (j=0; j<3; j++){
    			if (InState[i][j] == 0){
    				x = i;
    				y = j;
    			}
    		}
    	}
    
    	cout<<"x "<< x <<"y "<< y <<endl;
    
    	cout<<"The initial state selected is"<<endl;
    	for (i=0; i<3; i++){
    		cout<<InState[i][0]<<" "<<InState[i][1]<<" "<<InState[i][2]<<endl;
    	}
    
    	//reserve for final path
    	final.reserve(10);
    	
    	//define the root node
    	node root;
    	for (int i = 0; i<3; i++) { 
    		for (int j=0; j<3; j++){
    			root.state[i][j] = InState[i][j];
    		}
    	}
    	root.id=0;
    	//start vector list to find path to goal
    	root.list.push_back(root.id);
    	//find available moves for root
    	zero_state(x,y,moves);
    
    	/*cout<<"Available moves:"<<endl;
    	for (i=0; i<sizeof(moves); i++){
    		cout<<moves[i]<<endl;
    	}*/
    	aa=sizeof(moves);
    	a = aa;
    	//generate number of children from root, using the number of available moves
    	node *levela;
    	try {
    		levela = new node[aa];
    	} catch (bad_alloc xa) {
    		cout<<"Allocation Failure\n";
    		return 1;
    	}
    
    	if (leave!=true){
    
    	//********************put this in a do while loop.... must continue until goal is found*******
    
    	//max depth?????
    
    	//for each child of root generate their children the same way
    	for (int i=0; i<aa; i++){
    		//fill each node with required information 
    		levela[i].id = i+1;
    		//find available moves for each child
    		zero_position(levela[i].state,x,y);
    		zero_state(x,y,moves);
    		//define their parent
    		levela[i].parent=&root;
    		//define their states
    		copy(levela[i].state,root.state);
    		swap_tiles(levela[i].state,moves[i],x,y);
    		//define path to state
    		levela[i].list=root.list;
    		levela[i].list.push_back(levela[i].id);
    		// total number of children for all nodes at this level
    		children+=sizeof(moves);
    		//determine if goal state reached?
    		if (repeat_goal(levela[i].state,GoalState)) {
    					final=levela[i].list;
    					leave=true;
    					break;
    				}
    	}
    	}
    		
    		//define children for each node 
    		start=aa;
    		int bb=children;
    		node *levelb;
    		try {
    			levelb = new node[bb];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    
    		if (!leave){
    		
    		children=0;
    		for (int j=0; j<start; j++){
    			//determine parent node moves
    			zero_position(levela[j].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int jj=0; jj<child;jj++){
    				//fill each node with required information
    				levelb[jj].id = start+jj;
    				//define their parent
    				levelb[jj].parent=&levela[j];
    				//define their states
    				copy(levelb[jj].state,levela[j].state);
    				swap_tiles(levelb[jj].state,moves[jj],x,y);
    				//define path to state
    				levelb[jj].list=levela[j].list;
    				levelb[jj].list.push_back(levelb[jj].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(levelb[jj].state,GoalState)) {
    					final=levelb[jj].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		b=aa-start;
    		}
    		
    		//define children for each node 
    		int cc=children;
    		node *levelc;
    		//levelc = new node[cc];
    		try {
    			levelc = new node[cc];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    		if (!leave){
    		stop=aa;
    		
    		children=0;
    		for (int k=start; k<stop; k++){
    			//determine parent node moves
    			zero_position(levelb[k].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int kk=0; kk<child;kk++){
    				//fill each node with required information
    				levelc[kk].id = stop+kk;
    				//define their parent
    				levelc[kk].parent=&levelb[k];
    				//define their states
    				copy(levelc[kk].state,levelb[k].state);
    				swap_tiles(levelc[kk].state,moves[kk],x,y);
    				//define path to state
    				levelc[kk].list=levelb[k].list;
    				levelc[kk].list.push_back(levelc[kk].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(levelc[kk].state,GoalState)) {
    					final=levelc[kk].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		c = aa-stop;
    		}
    
    		//define children for each node 
    		int dd=children;
    		node *leveld;
    		//leveld = new node[dd];
    		try {
    			leveld = new node[dd];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    		if (!leave){		
    		start=stop;
    		stop=aa;
    		children=0;
    		for (int k=start; k<stop; k++){
    			//determine parent node moves
    			zero_position(levelc[k].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int kk=0; kk<child;kk++){
    				//fill each node with required information
    				leveld[kk].id = stop+kk;
    				//define their parent
    				leveld[kk].parent=&levelc[k];
    				//define their states
    				copy(leveld[kk].state,levelc[k].state);
    				swap_tiles(leveld[kk].state,moves[kk],x,y);
    				//define path to state
    				leveld[kk].list=levelc[k].list;
    				leveld[kk].list.push_back(leveld[kk].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(leveld[kk].state,GoalState)) {
    					final=leveld[kk].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		d = aa-stop;
    		}
    		
    		if (leave){
    			cout<<"The solution is "<<endl;
    			display(root.state);
    			for (int i=0; i<a; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levela[i].id){
    						display(levela[i].state);
    				}
    			}
    			}
    			for (int i=0; i<b; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levelb[i].id){
    						display(levelb[i].state);
    				}
    			}
    			}
    			for (int i=0; i<c; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levelc[i].id){
    						display(levelc[i].state);
    				}
    			}
    			}
    			
    			for (int i=0; i<d; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == leveld[i].id){
    						display(leveld[i].state);
    				}
    			}
    			}
    		}
    			
    	delete levela;
    	delete levelb;
    	delete levelc;
    	delete leveld;
    
    	system ("pause");
    	
    	return 0;
    }

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ vector length error at run time

    Quote Originally Posted by bloo View Post
    the code compiles, but when debugging there is an error
    First thing you should know is that successful compilation means nothing when it comes to actually running the program. A successful compilation means the program is syntactically correct,. i.e. the C++ syntax is valid -- it doesn't determine if the program is logically correct or will run correctly.

    Second, you say you're using vectors, but for the things you should be using vector for, you don't use it. Things like this:
    Code:
    levela = new node[aa];
    //...
    levelb = new node[bb];
    //...
    levelc = new node[cc];
    //...
    leveld = new node[dd];
    
    	delete levela;
    	delete levelb;
    	delete levelc;
    	delete leveld;
    
    //..etc
    Code like this is exactly what vector is supposed to replace. You then mishandle the pointers at the end, namely you use the wrong form of delete (you use "delete" when you should use "delete[]"). You also have a memory leak if levelb or levelc or leveld throw an exception on new, since you didn't deallocate the memory for the previous levels (you only do a return).

    Also, I didn't even check if there is more mismanagement with these pointers.

    The way you replace this with vector is simple:
    Code:
    std::vector<node> levela(aa);
    //...
    std::vector<node> levelb(bb);
    //..
    std::vector<node> levelc(cc);
    //..
    std::vector<node> leveld(dd);
    etc..
    If an exception is thrown, you now shouldn't call delete, as the vector will clean up the memory automatically when the function exits or returns for any reason whatsoever. IMO the number 1 reason to use vectors is for things like this, but you completely missed using them here.

    Then you do this:
    Code:
             node::node() { list.reserve(10); }
             //...
    	//reserve for final path
    	final.reserve(10);
    Don't you mean "resize()"? The reserve() does not create valid entries in a vector. All it does is make sure there is preallocated memory up-front so that subsequent insertions in the vector take less time. The resize() is the function that actually creates entries in the vector.
    I feel logically my code is correct and so i have not posted everything. Also it is a lot to read, but i have posted all the bits concerning the vectors.
    More times then not, code that is not posted is the cause of the error. If you corrupt memory anywhere in your program, it can affect other parts of the code that you may think it won't affect.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; September 7th, 2011 at 03:17 PM.

  3. #3
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    thanks for the reply, firstly i did mention that i felt my code was logically correct and i do understand that compiling means syntax, that's why i stated that it compiled.

    secondly as far as i know i was not trying to use vectors here:
    Code:
    levela = new node[aa];
    //...
    levelb = new node[bb];
    //...
    levelc = new node[cc];
    //...
    leveld = new node[dd];
    
    	delete levela;
    	delete levelb;
    	delete levelc;
    	delete leveld;
    
    //..etc
    here i'm trying to create arrays of objects because i'm building a tree, and cannot predetermine how many nodes will be needed at each stage. so i tried to automatically create them, as i mentioned before i'm doing a bfs search, so my idea was to add a vector to each node as they created and create them in the way a bfs would be performed in a tree, so i'm "creating and searching" at the same time. so each node in the tree will have a vector which will store the path to it.

    as for the reserve()
    Code:
             node::node() { list.reserve(10); }
             //...
    	//reserve for final path
    	final.reserve(10);
    here i did mean to preallocate memory in an effort to solve the error i mentioned in my previous post. i will post my complete code now. forgive me if u still feel i should create the nodes with vectors, i have spent a good few days on this code and i think u may be misunderstanding the point of the entire code.

  4. #4
    Join Date
    Feb 2002
    Posts
    4,640

    Re: C++ vector length error at run time

    Paul was suggesting that you should use vectors there, since you're already using them in other places.

    Using 'reserve' is fine, as long as you know how it works. For example, this is wrong, but will compile fine:
    Code:
    std::vector<int> myVec;
    myVec.reserve(50);
    myVec[48] = 42;
    Perhaps you meant to use "resize"?

    Viggy

  5. #5
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    header file:

    Code:
    #ifndef HEADER_H
    #define HEADER_H
    
    #include <vector>
    using std::vector;
    class node{
    
    public:
    		int state[3][3];
    		int id;
    		char action;
    		vector<int> list;
    		node* parent;
    		node();
    		~node();
    };
    
    void zero_position(int [3][3], int&, int&);
    
    void zero_state(int r, int c, char *moves);
    
    void copy(int [3][3], int [3][3]);
    
    void swap_tiles(int [3][3], char, int, int);
    
    bool repeat_goal(int [3][3], int [3][3]);
    
    void display(int [3][3]);
    
    #endif
    definitions:
    Code:
    #include "header.h"
    #include <iostream>
    
    node::node() { list.reserve(10); }
    node::~node() { }
    
    void zero_position(int ste[3][3], int &r, int &c){
    		//at this point we find the position of zero or the blank
    	for (int i = 0; i<3; i++) { 
    		for (int j=0; j<3; j++){
    			if (ste[i][j] == 0){
    				r = i;
    				c = j;
    			}
    		}
    	}
    }
    
    void zero_state(int r, int c, char *moves){
    	switch (r){
    		case 1:
    			switch (c){
    				case 1:	{
    					moves[0]='l';
    					moves[1]='u';
    					break;
    						}
    				case 2: {
    					moves[0]='r';
    					moves[1]='l';
    					moves[2]='u';
    					break;
    						}
    				case 3: {
    					moves[0]='r';
    					moves[1]='u';
    					break;
    						}
    			}
    		break;
    		case 2:
    			switch (c){
    				case 1:	{
    					moves[0]='d';
    					moves[1]='l';
    					moves[2]='u';
    					break;
    						}
    				case 2: {
    					moves[0]='r';
    					moves[1]='l';
    					moves[2]='u';
    					moves[3]='d';
    					break;
    						}
    				case 3: {
    					moves[0]='r';
    					moves[1]='u';
    					moves[2]='d';
    					break;
    						}
    			}
    		break;
    
    		case 3:
    			switch (c){
    				case 1:	{
    					moves[0]='d';
    					moves[1]='l';
    					break;
    						}
    				case 2: {
    					moves[0]='r';
    					moves[1]='l';
    					moves[3]='d';
    					break;
    						}
    				case 3: {
    					moves[0]='r';
    					moves[2]='d';
    					break;
    						}
    			}
    		break;
    
    	}
    	return;
    }
    
    void copy(int one[3][3], int two[3][3]){
    
    	for (int r = 0; r<3; r++) { 
    		for (int c=0; c<3; c++){
    			one[r][c]=two[r][c];
    			}
    		}
    }
    
    void swap_tiles(int s[3][3], char mov, int x, int y){
    	int a;
    	switch (mov){
    		case 'u': {
    			a = x-1;
    			s[x][y]=s[a][y];
    			s[a][y]=0;
    			break;
    				  }
    		case 'd': {
    			a = x+1;
    			s[x][y]=s[a][y];
    			s[a][y]=0;
    			break;
    				  }
    
    		case 'l': {
    			a = y-1;
    			s[x][y]=s[x][a];
    			s[x][a]=0;
    			break;
    				  }
    		case 'r': {
    			a = y+1;
    			s[x][y]=s[x][a];
    			s[x][a]=0;
    			break;
    				  }
    	}
    }
    
    bool repeat_goal(int state[3][3], int other[3][3]){
    int count=0;
    	for (int i = 0; i<3; i++) { 
    		for (int j=0; j<3; j++){
    			if (state[i][j] == other[i][j]){
    				count++;
    			}
    		}
    	}
    
    	if (count == 9){ return true;}
    	else return false;
    }
    
    void display(int st[3][3]){
    		for (int i=0; i<3; i++){
    			std::cout<<st[i][0]<<" "<<st[i][1]<<" "<<st[i][2]<<std::endl;
    		}
    }
    main:
    Code:
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include "header.h"
    
    int choice;
    int i,j,x,y,a,b,c,d,aa, children, start, stop, child;
    int InState [3][3];
    int GoalState [3][3];
    bool leave = false;
    char moves[4];
    std::vector<int> final;
    
    using namespace std;
    int main(){
    
    
    	GoalState[0][0] = 1;
    	GoalState[0][1] = 2;
    	GoalState[0][2] = 3;
    	GoalState[1][0] = 8;
    	GoalState[1][1] = 0;
    	GoalState[1][2] = 4;
    	GoalState[2][0] = 7;
    	GoalState[2][1] = 6;
    	GoalState[2][2] = 5;
    
    	cout<<"Welcome to the 8-puzzle"<<endl;
    		
    	cout<<"Our goal state is :"<<endl;
    	cout<<endl;
    	for (i=0; i<3; i++){
    		cout<<GoalState[i][0]<<" "<<GoalState[i][1]<<" "<<GoalState[i][2]<<endl;
    	}
    
    	cout<<"\nEnter Initial State one integer at a time:"<<endl;
    	cout<<"Please use integers 0 to 8 only where 0 represents the blank tile"<<endl;
    	
    	for (i = 0; i<3; i++) { 
    		for (j=0; j<3; j++){
    			cin>> InState[i][j];
    			if (InState[i][j] > 8) {
    				cout<<"number should be from 0 to 8. Re-enter"<<endl;
    				cin>> InState[i][j];}
    
    		}
    	}
    
    	//at this point we find the position of zero or the blank
    	for (i = 0; i<3; i++) { 
    		for (j=0; j<3; j++){
    			if (InState[i][j] == 0){
    				x = i;
    				y = j;
    			}
    		}
    	}
    
    	cout<<"x "<< x <<"y "<< y <<endl;
    
    	cout<<"The initial state selected is"<<endl;
    	for (i=0; i<3; i++){
    		cout<<InState[i][0]<<" "<<InState[i][1]<<" "<<InState[i][2]<<endl;
    	}
    
    	//reserve for final path
    	final.reserve(10);
    	
    	//define the root node
    	node root;
    	for (int i = 0; i<3; i++) { 
    		for (int j=0; j<3; j++){
    			root.state[i][j] = InState[i][j];
    		}
    	}
    	root.id=0;
    	//start vector list to find path to goal
    	root.list.push_back(root.id);
    	//find available moves for root
    	zero_state(x,y,moves);
    
    	/*cout<<"Available moves:"<<endl;
    	for (i=0; i<sizeof(moves); i++){
    		cout<<moves[i]<<endl;
    	}*/
    	aa=sizeof(moves);
    	a = aa;
    	//generate number of children from root, using the number of available moves
    	node *levela;
    	try {
    		levela = new node[aa];
    	} catch (bad_alloc xa) {
    		cout<<"Allocation Failure\n";
    		return 1;
    	}
    
    	if (leave!=true){
    
    	//********************put this in a do while loop.... must continue until goal is found*******
    
    	//max depth?????
    
    	//for each child of root generate their children the same way
    	for (int i=0; i<aa; i++){
    		//fill each node with required information 
    		levela[i].id = i+1;
    		//find available moves for each child
    		zero_position(levela[i].state,x,y);
    		zero_state(x,y,moves);
    		//define their parent
    		levela[i].parent=&root;
    		//define their states
    		copy(levela[i].state,root.state);
    		swap_tiles(levela[i].state,moves[i],x,y);
    		//define path to state
    		levela[i].list=root.list;
    		levela[i].list.push_back(levela[i].id);
    		// total number of children for all nodes at this level
    		children+=sizeof(moves);
    		//determine if goal state reached?
    		if (repeat_goal(levela[i].state,GoalState)) {
    					final=levela[i].list;
    					leave=true;
    					break;
    				}
    	}
    	}
    		
    		//define children for each node 
    		start=aa;
    		int bb=children;
    		node *levelb;
    		try {
    			levelb = new node[bb];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    
    		if (!leave){
    		
    		children=0;
    		for (int j=0; j<start; j++){
    			//determine parent node moves
    			zero_position(levela[j].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int jj=0; jj<child;jj++){
    				//fill each node with required information
    				levelb[jj].id = start+jj;
    				//define their parent
    				levelb[jj].parent=&levela[j];
    				//define their states
    				copy(levelb[jj].state,levela[j].state);
    				swap_tiles(levelb[jj].state,moves[jj],x,y);
    				//define path to state
    				levelb[jj].list=levela[j].list;
    				levelb[jj].list.push_back(levelb[jj].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(levelb[jj].state,GoalState)) {
    					final=levelb[jj].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		b=aa-start;
    		}
    		
    		//define children for each node 
    		int cc=children;
    		node *levelc;
    		//levelc = new node[cc];
    		try {
    			levelc = new node[cc];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    		if (!leave){
    		stop=aa;
    		
    		children=0;
    		for (int k=start; k<stop; k++){
    			//determine parent node moves
    			zero_position(levelb[k].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int kk=0; kk<child;kk++){
    				//fill each node with required information
    				levelc[kk].id = stop+kk;
    				//define their parent
    				levelc[kk].parent=&levelb[k];
    				//define their states
    				copy(levelc[kk].state,levelb[k].state);
    				swap_tiles(levelc[kk].state,moves[kk],x,y);
    				//define path to state
    				levelc[kk].list=levelb[k].list;
    				levelc[kk].list.push_back(levelc[kk].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(levelc[kk].state,GoalState)) {
    					final=levelc[kk].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		c = aa-stop;
    		}
    
    		//define children for each node 
    		int dd=children;
    		node *leveld;
    		//leveld = new node[dd];
    		try {
    			leveld = new node[dd];
    		} catch (bad_alloc xa) {
    			cout<<"Allocation Failure\n";
    			return 1;
    		}
    		if (!leave){		
    		start=stop;
    		stop=aa;
    		children=0;
    		for (int k=start; k<stop; k++){
    			//determine parent node moves
    			zero_position(levelc[k].state,x,y);
    			zero_state(x,y,moves);
    			child=sizeof(moves);
    			aa+=child;
    			// total number of children for all nodes at this level
    			children+=sizeof(moves);
    			for (int kk=0; kk<child;kk++){
    				//fill each node with required information
    				leveld[kk].id = stop+kk;
    				//define their parent
    				leveld[kk].parent=&levelc[k];
    				//define their states
    				copy(leveld[kk].state,levelc[k].state);
    				swap_tiles(leveld[kk].state,moves[kk],x,y);
    				//define path to state
    				leveld[kk].list=levelc[k].list;
    				leveld[kk].list.push_back(leveld[kk].id);
    				
    				//determine if goal state reached?
    				if (repeat_goal(leveld[kk].state,GoalState)) {
    					final=leveld[kk].list;
    					leave=true;
    					break;
    				}
    			}
    		}
    		d = aa-stop;
    		}
    		
    		if (leave){
    			cout<<"The solution is "<<endl;
    			display(root.state);
    			for (int i=0; i<a; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levela[i].id){
    						display(levela[i].state);
    				}
    			}
    			}
    			for (int i=0; i<b; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levelb[i].id){
    						display(levelb[i].state);
    				}
    			}
    			}
    			for (int i=0; i<c; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == levelc[i].id){
    						display(levelc[i].state);
    				}
    			}
    			}
    			
    			for (int i=0; i<d; i++){
    				for (int j=0; j<final.size();j++){
    					if (final[j] == leveld[i].id){
    						display(leveld[i].state);
    				}
    			}
    			}
    		}
    			
    	delete levela;
    	delete levelb;
    	delete levelc;
    	delete leveld;
    
    	system ("pause");
    	
    	return 0;
    }

  6. #6
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    Quote Originally Posted by MrViggy View Post
    Paul was suggesting that you should use vectors there, since you're already using them in other places.

    Using 'reserve' is fine, as long as you know how it works. For example, this is wrong, but will compile fine:
    Code:
    std::vector<int> myVec;
    myVec.reserve(50);
    myVec[48] = 42;
    Perhaps you meant to use "resize"?

    Viggy
    okay, but i don't totally understand how to use the vector in the first place and as i mentioned previously the vector is giving me the runtime error.
    i do not want to resize them, as i explain the error says that the vector is too long and that's why i wanted to preallocate memory to it, should i resize it?

    please take a look at my entire code and let me know if it's possible to simply resolve the current error, i know it could be completely wrong. all help is appreciated.

    if Paul could please explain how i would use this, as u can see i tried to do everything with very simple knowledge of c++
    Code:
    std::vector<node> levela(aa);
    //...
    std::vector<node> levelb(bb);
    //..
    std::vector<node> levelc(cc);
    //..
    std::vector<node> leveld(dd);

  7. #7
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: C++ vector length error at run time

    Quote Originally Posted by bloo View Post
    okay, but i don't totally understand how to use the vector in the first place
    A vector is designed to be a drop-in replacement for a dynamic array allocated with "new". That tells you 95% of what you need to know about vectors.

    When you hit the runtime error, which line is indicated in your debugger?

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ vector length error at run time

    Quote Originally Posted by bloo View Post
    i do not want to resize them, as i explain the error says that the vector is too long
    There is no such thing as an error saying a vector is "too long". If anything, the vector is too small, and you're attempting to index an invalid entry.
    and that's why i wanted to preallocate memory to it, should i resize it?
    Understand the difference between resize() and reserve(), and I mentioned this already in my first post.

    The reserve() function does not create entries in the vector. Therefore this code:
    Code:
    std::vector<int> t;
    t.reserve(10);
    t[5] = 1; // access the sixth element.  Error!!
    will not work. The code above does not mean that the vector has 10 entries in it. It has zero entries, so accessing element 6, for example, is illegal and produce a runtime error for debug versions of Visual C++. This is probably the error you are referring to. The main use for reserve() is again, to preallocate memory so that subsequent calls to add items in the vector occur faster.

    The resize() actually places 10 empty elements in the vector. So the above code will work if you replace reserve() with resize(). So, get rid of the reserve() and use resize() -- you want to access element x of a vector, that vector better have at least x+1 elements in it, and reserve() does not accomplish this -- resize() does.

    I think you're confused as to what resize() does, because the name of the function is "resize". When you declare a vector, it is initially empty:
    Code:
    std::vector<int> v;
    The vector v has no entries. Now what if you want it to have 10 entries, and you already declared it with 0 entries? You call resize().
    Code:
    std::vector<int> v;
    //.. a bunch of code here, who cares
    // now we want to make v have 10 elements
    v.resize( 10 );
    Understand now? resize(n) means "make my vector have n elements".
    if Paul could please explain how i would use this, as u can see i tried to do everything with very simple knowledge of c++
    A vector is a dynamic array -- you are trying to do dynamic arrays using the tricky and error-prone new[]/delete[]. So instead of using new[]/delete[] use vector, as that is exactly what it's designed to do. In addition, your code has a memory leak because of you mishandling new[]/delete[], so even if you didn't realize this in the beginning, we here are going to look at all the code you posted and comment on anything that is amiss.

    As to how to use it, you use it exactly as I stated previously -- get rid of new[] and delete[] and use vector as a dynamic array of node.
    Code:
    std::vector<node> levela(aa);
    //...
    std::vector<node> levelb(bb);
    //..
    std::vector<node> levelc(cc);
    //..
    std::vector<node> leveld(dd);
    That code is all you need, and you remove those lines that use new[]/delete[]. You also don't need those try/catches any more, and you don't need those delete's at the end of main(). In other words, your code will become smaller and safer using vector than when you were using new[]/delete[].

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; September 7th, 2011 at 04:51 PM.

  9. #9
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: C++ vector length error at run time

    Quote Originally Posted by Paul McKenzie View Post
    There is no such thing as an error saying a vector is "too long".
    Perhaps unless something (completely unrelated) has corrupted some data members private to the vector object, thereby making the vector appear larger than vector::max_size() and triggering some internal assertion.

    According to a little experiment I made, in a VC++ 2010 debug build vector<node>::max_size() (where node is the OP's class with commented-out c'tor and d'tor) returns 63161283 (0x3C3C3C3), which is way less than numeric_limits<size_type>::max().

    Just an idea...

    For reference: Is there a maximum number a vector can take?
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  10. #10
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    Quote Originally Posted by Lindley View Post
    A vector is designed to be a drop-in replacement for a dynamic array allocated with "new". That tells you 95% of what you need to know about vectors.

    When you hit the runtime error, which line is indicated in your debugger?
    Hi lindley I have tried what Paul suggested... using resize instead of reserve and I still get the same run time error, however I will use his other suggestions now and try again.

    The error I receive is: Unhandled exception at 0x77a915ee in 8puzzle.exe: Microsoft C++ exception: std::length_error at memory location 0x0045f0cc
    I am using Visual Studio 2008, with the library update.

    Quote Originally Posted by Paul McKenzie View Post
    There is no such thing as an error saying a vector is "too long". If anything, the vector is too small, and you're attempting to index an invalid entry.
    Understand the difference between resize() and reserve(), and I mentioned this already in my first post.

    The reserve() function does not create entries in the vector. Therefore this code:
    Code:
    std::vector<int> t;
    t.reserve(10);
    t[5] = 1; // access the sixth element.  Error!!
    will not work. The code above does not mean that the vector has 10 entries in it. It has zero entries, so accessing element 6, for example, is illegal and produce a runtime error for debug versions of Visual C++. This is probably the error you are referring to. The main use for reserve() is again, to preallocate memory so that subsequent calls to add items in the vector occur faster.

    The resize() actually places 10 empty elements in the vector. So the above code will work if you replace reserve() with resize(). So, get rid of the reserve() and use resize() -- you want to access element x of a vector, that vector better have at least x+1 elements in it, and reserve() does not accomplish this -- resize() does.

    I think you're confused as to what resize() does, because the name of the function is "resize". When you declare a vector, it is initially empty:
    Code:
    std::vector<int> v;
    The vector v has no entries. Now what if you want it to have 10 entries, and you already declared it with 0 entries? You call resize().
    Code:
    std::vector<int> v;
    //.. a bunch of code here, who cares
    // now we want to make v have 10 elements
    v.resize( 10 );
    Understand now? resize(n) means "make my vector have n elements".
    A vector is a dynamic array -- you are trying to do dynamic arrays using the tricky and error-prone new[]/delete[]. So instead of using new[]/delete[] use vector, as that is exactly what it's designed to do. In addition, your code has a memory leak because of you mishandling new[]/delete[], so even if you didn't realize this in the beginning, we here are going to look at all the code you posted and comment on anything that is amiss.
    I do understand now, thank you for that explanation. I have tried this and still get the error which I stated above. However I will continue to make the changes you suggested and I will post my results. Thank you!

  11. #11
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    Quote Originally Posted by Lindley View Post
    A vector is designed to be a drop-in replacement for a dynamic array allocated with "new". That tells you 95% of what you need to know about vectors.

    When you hit the runtime error, which line is indicated in your debugger?
    oh I forgot to say that the debugger stops at a line in the vector file:
    _THROW(length_error, "vector<T> too long");

  12. #12
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    Quote Originally Posted by Paul McKenzie View Post
    As to how to use it, you use it exactly as I stated previously -- get rid of new[] and delete[] and use vector as a dynamic array of node.
    Code:
    std::vector<node> levela(aa);
    //...
    std::vector<node> levelb(bb);
    //..
    std::vector<node> levelc(cc);
    //..
    std::vector<node> leveld(dd);
    That code is all you need, and you remove those lines that use new[]/delete[]. You also don't need those try/catches any more, and you don't need those delete's at the end of main(). In other words, your code will become smaller and safer using vector than when you were using new[]/delete[].

    Regards,

    Paul McKenzie
    Hi Paul, I just attempted changing this code now. The previous error does not come up, but instead I have a new error: Debug Assertion Failed! Program: ...8puzzle.exe File: ....\include\vector Line: 779
    Expression: vector subscript out of range

    By using vectors here, is there anything else I need to change, I read a bit and I think the way you access the objects is the same, is that correct? What other changes do I need to suit using vectors here?

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: C++ vector length error at run time

    Quote Originally Posted by bloo View Post
    Hi Paul, I just attempted changing this code now. The previous error does not come up, but instead I have a new error: Debug Assertion Failed! Program: ...8puzzle.exe File: ....\include\vector Line: 779
    Expression: vector subscript out of range
    That is much better. Now you are told exactly what you were doing wrong before, and probably the reason why you were crashing from the beginning.

    When you were using new[]/delete[] and pointers, you were overwriting memory. The problem is that overwriting memory when using raw pointers does not usually reveal itself when you run the program. Instead, you corrupt other areas of the program thereby getting the messages that "vector too long".

    Now that you've changed to vector from using pointers, it is obviously clear that you were accessing invalid memory, but this time you get the indication that you're accessing an invalid vector entry. That is also the advantage of using vector (at least in debug mode). Visual C++ checks if you're using operator[] illegally, and you are.

    The error means that your vector has a maximum of x elements, and you're writing beyond element x-1 (elements start at 0 and go to x-1). This is simple to diagnose, but you have to debug your program as to why you're writing beyond the legal limits of your vector.
    By using vectors here, is there anything else I need to change, I read a bit and I think the way you access the objects is the same, is that correct?
    It is exactly the same.
    What other changes do I need to suit using vectors here?
    None. You need to debug your code, as your quote below isn't correct:
    I feel logically my code is correct and so i have not posted everything
    Obviously, your program isn't logically correct. Time to debug it.

    Regards,

    Paul McKenzie

  14. #14
    Join Date
    Sep 2011
    Posts
    8

    Re: C++ vector length error at run time

    Quote Originally Posted by Paul McKenzie View Post
    Obviously, your program isn't logically correct. Time to debug it.

    Regards,

    Paul McKenzie
    Thanks so much! will try to do that.

  15. #15
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: C++ vector length error at run time

    Quote Originally Posted by bloo View Post
    oh I forgot to say that the debugger stops at a line in the vector file:
    _THROW(length_error, "vector<T> too long");
    Okay, now look further up the call stack and see which part of your code is triggering that. Also look at what the internals of the vector look like at that time.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured