Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am working on a chess game in c++ .
I have the classes :
class piece
{
protected :
point position ;
char represent ;
bool colour; // true for player 1 = green , false for player 0 = blue
public :
virtual ~piece() ;
bool find_player(piece* to_check, int num);
char get_char() ;
bool get_colour() ;
virtual bool move_setup(point source, point dest, piece* arr[][SIZE] ) = 0 ;
virtual bool move(point source, point dest, piece* arr[][SIZE]) = 0;
bool same_player(point dest, piece* arr[][SIZE], int* num);
};
class board
{
private:
piece* arr[SIZE][SIZE] ;
public :
board();
void free_borad();
void set_piece(int x , int y , int type , bool colour );
void print_board();
void move(point source , point dest);
void set_colour(int i , int j , bool reset );
};
class pawn : public piece
{
public :
pawn(point position , bool colour );
~pawn();
virtual bool move_setup(point source, point dest, piece* arr[][SIZE]);
virtual bool move(point source, point dest, piece* arr[][SIZE]);
bool if_forward(point source, point dest);
bool if_diagonal(point source, point dest, int* offset);
};
I have a class for every piece in which I have implemented the move functions.
the classes are not relevant so I just put a pawn class for the example .
the board move function :
void board::move(point source, point dest)
{
if (arr[source.get_x()][source.get_y()]) // if not empty
{
int x = source.get_x(), y = source.get_y() ;
if (arr[x][y]->move_setup(source, dest, arr ) ) // if the piece can move there
{
delete arr[dest.get_x()][dest.get_y()];
arr[dest.get_x()][dest.get_y()] = arr[source.get_x()][source.get_y()];
arr[source.get_x()][source.get_y()] = NULL;
std::cout << " Succes! " << std::endl;
}
else
{
// error
}
}
else // empty
{
// error
}
}
my program crashes at the line
if (arr[x][y]->move_setup(source, dest, arr ) )
I have debbuged it using the VS debugger , and realized that the crash occurs when sending the array , error message :
Access violation reading location 0xFFFFFFFF.
I have tried to send it in many different ways , and nothing works ,
but this method is exactlly how a friend of mine did it , and it works just fine for him .
can anyone help ?
thank you .
Arrays in C++ are 0-based, which means the index of the first element is 0. If your coordinates are 1-based, it means you are accessing an element one row and one column off in the array. That in turn leads to breaching the bounds of the array and your crash. The solution is either to adopt a 0-based coordinate system or subtract 1 from the x/y coordinates when accessing the array.
Related
I tried to make the classes hold RAII standards (as I get it .. I'm a hobby programmer), but the compiler/debugger complained about missing constructors (with empty brackets), so I added them + set_value() functions.
The point of elaborating so much on a simple rectangle is to lift the cloudiness of integrating GUI-types (top-down types like buttons and text-fields) from the foreground problem I'm trying to handle: openGL 2D & 3d graphics living in a lower-left coordinatesystem.
enum class eAnker:int{
high_left,
high_right,
low_left,
low_right,
}
class anker
{
friend node_handler;
public:
anker(){};
anker(glm::dvec2 Vec2):pPoint( new glm::dvec2(Vec2) ){};
anker(glm::dvec2 Vec2, eAnker ea):pPoint( new glm::dvec2(Vec2) ),anker_type(ea){};
virtual ~anker(){ delete pPoint; };
void set_value(glm::dvec2){pPoint=new glm::dvec2(v);}
void set_anchor_type( eAnker ea){ anker_type=ea; }
bool operator<( anker& a ){ return (pPoint->x<a.pPoint->x)<(pPoint->y<a.pPoint->y); };
protected:
glm::dvec2* pPoint;
eAnker anker_type;
};
class nRect:public anker
{
friend node_handler;
public:
nRect(){};
nRect(glm::dvec2 p):anker(p){};
nRect(glm::dvec2 p,double lineHeight, double letterWidth):anker(p),plHeight( new double(lineHeight)), plWidth( new double(letterWidth) ){};
virtual ~nRect(){
delete plHeight;
delete plWidth;
};
void set_dims( double Ww, double Lh ){
plWidth= new double(Ww*LETTER_PIXEL_WIDTH);
plHeight=new double(Lh*LINE_PIXEL_HEIGHT);
}
protected:
double* plHeight;
double* plWidth;
};
class node:public nRect
{
friend node_handler;
public:
node(){};
node(glm::dvec2 p):nRect(p){};
node(glm::dvec2 p, double wW, double lH):nRect(p,wW,lH){};
virtual ~node(){};
void mouse_up(){
on_click();
};
virtual void on_click(){
/*
bool b = !set_bit::is_closed(myBits);
set_bit::as_closed(myBits,b);
*/
};
protected:
vector<node>::iterator iParent;
bitset<32> myBits;
string string_data;
double my_ratio;
glm::dvec2 cursor_old;
};
class node_handler
{
public:
node_handler(){}
~node_handler(){};
void set_root( glm::dvec2 anker, double pixel_width, double pixel_height ){
if(!root_lock){
node n(anker,pixel_width/25.0d,pixel_height/12.0d) ;
n.string_data="root";
n.iParent = nodes.end();
nodes.resize(10);
nodes.at(0) = n ;
current=nodes.begin();
root_lock=true;
node_counter++;
}
else{
//cout << "BEEP nodes.root-error\n" << char(7);
}
}
void split_current( double ratio, bool as_horizontal ){
pair<node,node> res = split(current,ratio,as_horizontal);
res.first.string_data="-closer";
res.first.iParent=current;
res.second.string_data="-farther";
res.second.iParent=current;
if(node_counter<int(nodes.size()) ) {
nodes.at(node_counter)=res.first;
current=nodes.begin()+node_counter;
node_counter++;
nodes.at(node_counter)=res.second;
node_counter++;
}
else{
cout << "no handler-space for more nodes\n" ;
}
//no errors so far. when leaving split_current(..), the execution halts with a SIGSEGV
}
protected:
int node_counter=0;
private:
pair<node,node>split( vector<node>::iterator& this_node, double ratio, bool as_horizontal ){
this_node->my_ratio=ratio;
double firstW, firstH;
double secW, secH;
glm::dvec2 afirst, asecond;
if(as_horizontal ){
// set values
}
return make_pair<node,node>( node(afirst ,firstW, firstH), node(asecond ,secW, secH) ) ;
}
vector<node>::iterator current;
vector<node> nodes;
bool root_lock{false};
};
/////////////////////
test in main:
node_handler nh;
glm::dvec2 minor=glm::dvec2(0.0d, 0.0d);
double width=800.0d;
double height=600.0d;
nh.set_root(minor,width,height);
nh.split_current( 1.0d/10.0d , true );
//see nh.split_current() where SIGSEGV happens
The debug error-trace leaves 10 lines, noone pointing to a specific line in my code:
ntdll!RtlAnsiSringToUnicodeString()
??()
std::basic_Ostream<.....
std::clog()
std::clog()
??()
msvcat!_iob()
vtable for ct::anker
std::piecewise_construct
link is a follow-up, on the same code, that probably contain the proper answer to the erratic behavior described. In short (as I understand it): classes with pointer-members needs customized copy/assignment operators these they are at work, without your notice, behind the code you write .. the default ones won't work.
I didn't provide them.
I have an abstract class with 2 pure virtual functions:
class CCobjectBase
{
public:
CCobjectBase();
virtual void setCordFigure(double *, int) = 0;
virtual double* getCord() = 0;
};
And a class that is derived from the abstract one:
class CTriangle : public CCobjectBase
{
public:
CTriangle();
~CTriangle();
void setCordFigure(double *, int);
double* getCord();
private:
double *m_cord;
int m_size;
}
void CTriangle :: setCordFigure(double *cord, int size)
{
m_cord = cord;
m_size = size;
}
double * CTriangle :: getCord()
{
return m_cord;
}
I used a vector of pointers to the abstract class:
std::vector<CCobjectBase *> m_objectBaseList;
And i create and store some values in this vector as follow:
m_objectBaseList.push_back(new CTriangle());
m_objectBaseList.at(m_objectBaseList.size() - 1) -> setCordFigure(coordonate, size);
The problem occurs when i try to display the values from the vector:
for(size_t i=0; i< m_objectBaseList.size(); i++)
{
double * cord = m_objectBaseList.at(i) -> getCord();
out<<cord[0]<<" "<<cord[1]<<" "<<cord[2]<<" "<<cord[3]<<" "<<cord[4]<<" "<<cord[5]<<endl;
}
It seems that all the objects have the same values stored. I tried multiple solution but i can not simply figure it out. If i give inputs as follow:
Object1: 1 2 3 4 5 6
Object2: 3 2 3 3 5 5
...
Objectn: 1 1 2 2 1 1
All objects have the value of Objectn:
Object1: 1 1 2 2 1 1
Object2: 1 1 2 2 1 1
...
Objectn: 1 1 2 2 1 1
The problem is not from the parameter coordonate because i tested in the setCordFigure(double *cord, int size){} function and it shows fine.
Any possible sugestions?
EDIT:
The portion of the code where I set the values is actually like this:
void MainWindow :: creazaObiecte(int numarOrdine, double *coordonate, int size)
{
QTextStream out(stdout);
switch(numarOrdine)
{
case 1:
m_objectBaseList.push_back(new CTriangle());
m_objectBaseList.at(m_objectBaseList.size() - 1) -> setCordFigure(coordonate, size);
break;
...
}
}
I use this function from each line of a file what I read. The portion of the code where I call this function is something like:
while(--condition--)
{
double coordonate[30]; //coordonate is used to store values as an array Ex: 20 30 12 2 32 12 etc
//fill coordonate with values from the line of the file
creazaObiecte(ordinClasa, coordonate, size); //ordinClasa is a variable that stores the index of the object (1 stands for triangle)
}
EDIT: My original answer was in a context where I didn't realise m_coord is meant to be an array, so was inappropriate.
Your operation setCordFigure just sets your m_coord member pointer to the passed argument. It does not not copy the underlying array. So in the end all your objects end up pointing to the same array.
You need to actually copy the array in your setCordFigure function. You could do this with naked arrays, but its better to use a vector. So this is possible code:
class CCobjectBase
{
public:
CCobjectBase();
virtual void setCordFigure(const std::vector<double>&) = 0;
virtual std::vector<double>& getCord() = 0;
};
class CTriangle : public CCobjectBase
{
public:
CTriangle();
~CTriangle();
void setCordFigure(const std::vector<double>&);
std::vector<double>& getCord();
private:
std::vector<double> m_cord;
int m_size;
}
void CTriangle :: setCordFigure(const std::vector<double>& cord)
{
m_cord = cord;
}
std::vector<double>& CTriangle :: getCord()
{
return m_cord;
}
Then your creation function becomes:
void MainWindow :: creazaObiecte(int numarOrdine, const std::vector<double>& coordonate)
{
QTextStream out(stdout);
switch(numarOrdine)
{
case 1:
m_objectBaseList.push_back(new CTriangle());
m_objectBaseList.at(m_objectBaseList.size() - 1) -> setCordFigure(coordonate);
break;
...
}
}
And your population function becomes:
while(--condition--)
{
std::vector<double> coordonate(30); //coordonate is used to store values as an array Ex: 20 30 12 2 32 12 etc
//fill coordonate with values from the line of the file
creazaObiecte(ordinClasa, coordonate); //ordinClasa is a variable that stores the index of the object (1 stands for triangle)
}
double *m_cord;
You are storing a pointer to the coordinate in your class.
void CTriangle :: setCordFigure(double *cord, int size)
Then, probably, you are reading the "input" into some variables, which are then referenced in your CTriangle objects. So as the values of the variables are changed, all of the objects are really pointing to the same stuff.
Hey hey I'm a c++ newb here... i would appriciate someone pointing out an apparent misunderstanding i have about pointers and vectors (may be something else). I'm trying to create a switch element that handles several sub states
class MotionSwitch: public StateSwitch, public IMotion
{
public:
MotionSwitch(){ initialize(); };
~MotionSwitch(){};
//Make Motion States
MotionState restState; //Initialized In _states at 0
MotionState motionState;//" " 1
MotionState spinState;//" " 2
std::vector<MotionState*> _states;
};
class MotionState: public State, public IMotion
{
...
String msg = "Hello Is Motion";
...
};
The _states vector is initialized like this...
void MotionSwitch::initialize()
{
//Add States In Order Of ENUM (Because It Matters!)
_states.push_back(&restState);
_states.push_back(&motionState);
_states.push_back(&spinState);
}
The in following application code only one of the following will print
MotionState *currentState = widget._motionSwitch._states.at(0);
widget._com.log( "State Message...");
widget._com.log( currentState -> msg); //Won't Print
widget._com.log( widget._motionSwitch.restState.msg ); //This WILL Print
I would appreciate any help i can get here from you code gods!
I just read Joel's blog post on unicode, and found the characters the I want to use to draw boxes in the console in this pdf from the unicode website.
Displaying these characters is simple enough when done directly with cout, i.e. the following does what it is supposed to do..
cout << u8"\u256C";
However, I am doing some overloading as shown in the following snippets, and I cannot figure out how to get the box characters to display correctly.
I render my data like so ...
// This is the main rendering code
ostream& operator<<(ostream& os, const DataGrid& dg)
{
for(auto row : dg.data)
{
string tmp; //Make empty string
for(auto col : row)
tmp.append( 1, dg.gfxString[col] );
os << tmp << endl;
}
return os;
}
Make it friends with my data model...
class DataGrid
{
public:
friend ostream& operator<<(ostream& os, const DataGrid& dg);
//EDIT: rest of class added on request
DataGrid(Rectangle _rect = Rectangle(Point(0,0), Point(5,5))) :
rect(_rect),
data ( vector<vector<p_t>> (_rect.getHeight(), vector<p_t>(_rect.getWidth(), p_t::EMPTY)) ){}
void addPoint(Point p, p_t type)
{
data[p.getY()][p.getX()] = type;
}
void addBorder()
{
//Top and bottom
fill_n(data[0].begin()+1, rect.getWidth()-2, p_t::BORDER_T);
fill_n(data[rect.getBtm()].begin()+1, rect.getWidth()-2, p_t::BORDER_B);
//Left and right hand border edges
for (int nn=1; nn<rect.getHeight()-1; ++nn){
addPoint(Point(rect.getLeft(), nn), p_t::BORDER_L);
addPoint(Point(rect.getRight(), nn), p_t::BORDER_R);
}
//Corners
addPoint(rect.getTL(), p_t::BORDER_TL);
addPoint(rect.getTR(), p_t::BORDER_TR);
addPoint(rect.getBL(), p_t::BORDER_BL);
addPoint(rect.getBR(), p_t::BORDER_BR);
}
private:
Rectangle rect;
vector<vector<p_t>> data; //p_t is an enum
//string gfxString = " abcdefghijklmnop"; //This works fine
string gfxString = u8"\u256C\u256C\u256C\u256C\u256C\u256C\u256C\u256C"; //Nope
};
Then attempt to render it with the following, but get gibberish ...
DataGrid p = DataGrid(Rectangle(Point(0,0), 40, 10));
p.addBorder();
cout << p;
If anyone can spot a fix, then that would be great. Thanks for reading.
I'd change gfxString to a vector of std::strings (or even a std::array):
// Probably in the final code, these are not all the same value
std::array<std::string, 8> gfxString = {
{ u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
, u8"\u256C"
}};
Or even just an array of const char*.
I have run into a problem while working with c++ over Linux.
I have a base Message class which looks like this:
class MsgBase
{
public:
MsgBase( unsigned int msgid );
map < unsigned int, MSGIEBase* > messageIE_Map; // map for IEs
unsigned int messageId; // 32 bit message id
};
class Der1 is derived from MsgBase and looks like:
class Der1 : public MsgBase
{
public:
Der1 ();
virtual ~Der1 ();
// IEs
MSGIE_UINT32 ueId;
MSGIE_String configFileName;
};
Here MSGIE_UINT32 and MSGIE_String are classes derived from MSGIEBase and therefore their address can be stored in the map defined in base class above.
When Der1 is constructed the address of ueId and configFileName is stored in the map.
Here if I print the size of map ( through gdb and in the program ) it comes to be 24.
[ _M_header = 16, _M_node_count = 4, _M_key_compare = 1, 3 byte padding I suppose ].
Till here everything is fine. Now the Der1 object pointer is put inside an event object and the event is post into a queue. The event class looks like:
class Event
{
public:
MsgBase* msgPtr;
};
A different thread removes the event from the queue, extracts the msgPtr and casts it into Der1 Pointer and this is where the problem starts.
Here if I print the size of the map in the program it is 21. That means the address of the next member in the MsgBase class i.e. messageId gets shifted by 3 bytes and so the value of messageId changes completely. (when seen through gdb, the address is still intact and so is the size of the map i.e. 24 ).
This is a word alignment issue to the best of my knowledge but why is the memory alignment not consistent in different functions and why does the address of a member of a class chage when the memory to the class has been allocated using new. I am using Linux 2.6.27. , gcc version 4.1.1. , RHEL-4.
For ruling out non-virtual destructor/copy/assignment problems, please add the following to MsgBase:
public:
virtual ~MsgBase();
private:
MsgBase(MsgBase const& other);
MsgBase& operator=(MsgBase const& other);
I will try to provide all the required information step by step:
Information 1 : The relevant code.
//Step 1: Create msg and fill message Id
MsgBase*msgPtr = new Der1();
// C'tor of Der1 is as follows:
Der1::Der1 ()
: MsgBase ( ATS_SUTD_EPCTESTER_ATTACH_SCENARIO_MsgId ), // msgid is 13( 0xd )
ueId ( IE_UE_KEY, "UE", false ),
configFileName ( IE_CONFIG_FILE_NAME_KEY, "Configuration File Name", false )
{
// Insert the IEs in the map
this->addIEEntry ( IE_UE_KEY, &ueId ); // this puts entries in the map
this->addIEEntry ( IE_CONFIG_FILE_NAME_KEY, &configFileName );
}
// Step 2: Declare event and post the event
Event* event = new Event ( eventId, "Event" );
event->setData( msgPtr, hdr);
// check the message id at this stage (
cout << "msgId = " << ( ( (Der1* )msgPtr )->messageId )<< endl; // Here it comes out
// to be 0xd which is correct
// post the event
AppClass::getInstance()->addEventAndSchedule ( event );
//The queue is a member of AppClass and has been defined as
std::list <EventBase* > eventQueue;
// The code which inserts data into the queue is as follows:
bool AppClass::addEventAndSchedule ( EventBase* ev )
{
if ( ev == NULL ) return false;
this->eventQueueMutex.acquireLock();
this->eventQueue.push_back( ev );
this->eventQueueMutex.releaseLock();
// Submit Job to Scheduler
bool status = JobScheduler::getInstance()->scheduleJob( this );
return status;
}
// The event class is
class Event: public EventBase
{
public:
Event ();
virtual ~Event ();
Event ( int evId );
Event ( int evId, string evName );
MsgBase* getMessagePtr ();
void setData ( MsgBase* mPtr, Header* hPtr )
private:
// Prevent copying
Event& operator= ( Event& ev );
Event ( Event& evBase );
MsgBase* msgPtr;
Header* hdrPtr;
};
void Event::setData ( MsgBase* mPtr, Header* hPtr )
{
this->msgPtr = mPtr;
this->hdrPtr = hPtr;
}
Step 3 : Extract the event and re-print the message Id
// The code which extracts data from the queue is as follows:
void AppClass::process ()
{
EventBase* beventPtr = NULL;
this->eventQueueMutex.acquireLock();
if ( !this->eventQueue.empty() )
{
beventPtr = (EventBase* )( this->eventQueue.front() );
this->eventQueue.pop_front();
}
else
{
isQueueEmpty = true;
}
this->eventQueueMutex.releaseLock();
Event* eventPtr = ( Event* )beventPtr ;
Der1* msgPtr = (Der1* )( eventPtr->getMessagePtr()) ;
cout << "msgId = " << msgPtr->messageId << endl; // This value
//comes out to be incorrect it is now 0xd000000 i.e. a 3 byte shift
}
Information 2 : Exact problem.
The exact problem is that the 'messasgeId' is getting changed in transition. Initially it is 0xd but after popping from the queue it becomes 0xd000000. Because of this all the processing stops. The address of this parameter also changes from 0x82bd7cc to 0x82bd7c9 when printed in the program. However when seen from gdb it is still 0x82bd7cc and the value is still 0xd.
Information 3 : Compiler Flags.
Compiler Flags are same for all the files and they are:
-O0 -g3 -Wall -fmessage-length=0