I apologize since this is rather a n00bish question, but I can't figure this one out.
class View //simplified
{
public:
ROILine* ROI() {return _roi;} //setter does some control stuff...
private:
ROILine *_roi;
}
class ROI : public eq::Object
{
public:
//virtual ROI(ROI* copy) = 0;
virtual ~ROI() {};
virtual uint32_t getType() = 0;
virtual void reset() = 0;
virtual bool addPoint( eq::Vector3f point ) = 0;
virtual bool previewPoint( eq::Vector3f point ) = 0;
virtual bool getNotationLocation( eq::Vector3f& point ) = 0;
virtual bool draw() = 0;
protected:
enum ROIType {
NONE = 0,
LINE,
POLY,
AREA,
VOLUME
};
enum ROIMeasure {
RM_LENGTH = 1,
RM_AREA,
RM_VOLUME,
};
private:
};
class ROILine : virtual public ROI
{
public:
ROILine();
ROILine(ROILine* copy);
ROILine(const ROILine& copy);
virtual ~ROILine() {SFLog(#"Destroying ROILine: 0x%x",this);};
void reset();
float distance() { return _start.distance(_end); }
// ROI Interface
uint32_t getType() { return ROI::LINE; }
virtual bool draw();
bool addPoint( eq::Vector3f point );
bool previewPoint( eq::Vector3f point );
bool getNotationLocation( eq::Vector3f& point );
eq::net::DataOStream& serialize(eq::net::DataOStream& os) ;
eq::net::DataIStream& deserialize(eq::net::DataIStream& is) ;
protected:
enum ROILineState { // RLS_
RLS_RESET,
RLS_START,
RLS_PREVIEW,
RLS_END,
};
private:
uint32_t _state;
eq::Vector3f _start;
eq::Vector3f _end;
};
ROILine::ROILine(const ROILine& copy) : ROI()
{
reset();
switch (copy._state)
{
case RLS_PREVIEW:
case RLS_END:
addPoint(eq::Vector3f(copy._start));
addPoint(eq::Vector3f(copy._end));
break;
case RLS_START:
addPoint(eq::Vector3f(copy._start));
break;
case RLS_RESET:
default:
break;
}
}
/*!
#abstract resets the line values and state
*/
void ROILine::reset()
{
_state = RLS_RESET;
_end = eq::Vector3f::ZERO;
_start = eq::Vector3f::ZERO;
}
/*!
#abstract if it has 2 points, draw the line. (_state > _PREVIEW)
#discussion assumes GL is already set up. Executes drawing commands.
#result true if the line was drawn
*/
bool ROILine::draw()
{
bool retVal = false;
if (_state >= RLS_PREVIEW) {
//glTranslatef(0.0f, 0.0f, -1.0f); //Back Up?
glColor3f( 1.0f, 0.0f, 0.0f ); //Red
glEnable( GL_LINE_SMOOTH );
glLineWidth( 1 );
glBegin( GL_LINES );
{
glVertex3fv( _start.array );
glVertex3fv( _end.array );
}
glEnd();
//glTranslatef(0.0f, 0.0f, 1.0f); // Return
retVal = true;
}
return retVal;
}
// Elsewhere...
View *v = getView(); // returns the view object
// Destroys each time, but works wonderfully
ROILine r = ROILine(*(v->ROI()));
r.draw();
// Does not work (EXC_BAD_ACCESS)
v->ROI()->draw();
// Does not work (EXC_BAD_ACCESS on draw());
ROILine *r = v->ROI();
r->draw(); // debug shows r != 0x0
The Errors I get are as follows when I break on r->draw() and continue.
[Switching to process 12453]
Current language: auto; currently objective-c++
Warning: the current language does not match this frame.
(gdb) continue
Program received signal: “EXC_BAD_ACCESS”.
The "EXC_BAD_ACCESS" occurs on r->draw() or v->ROI()->draw() It doesn't step into the program at all, just halts and bt gives me a ??
My copy constructor works, because the draw() function actually draws where it's supposed to (instead of !!##$!4!## land) What I don't udnerstand, is why copying the value works, but accessing v->ROI()->draw() does not. it MUST have v->ROI() in order to make the copy!!
yes? ... no?
so confused...
Thanks,
Assuming that everything in your copy constructor for ROILine is working correctly, then here is a possibility: Something has overwritten a few bytes of the ROILine instance returned by View::ROI().
Most likely, the first several bytes of a ROILine object contain a pointer to the virtual function table for that class. (At least this is what typical C++ implementations do.) If those bytes get overwritten then instead of calling through the virtual function table, the program would end up calling through garbage and would almost certainly crash.
However, when making a copy of an object through a copy constructor, that pointer to the virtual function table is probably not accessed at all (unless you were to make a call to a virtual function in the copy constructor). In that case, all the data is copied successfully to a new object that has a correct vtable pointer.
Since draw is vritual, this would explain why calling it on the copy works while calling it on the original does not.
If this is what is happening, then you need to figure out what is overwriting part of your ROILine instance. If that instance is part of another object, then it may be easy. If that instance has been heap allocated individually, then it could be somewhat harder.
I think there's something strange going on.
You said code containing this line works wonderfully:
ROILine r = ROILine(*(v->ROI()));
In this line you perform *(v->ROI()) successfully.
But you said that if you try to do ROILine *r = v->ROI() then the value of r is NULL.
I don't think these can both be true (because that would mean you've successfully dereferenced a NULL pointer). I can think of two reasons for this:
Calling them sequentially does not work. If you move the "works wonderfully" block below the others, does it fail? If so, you may be copying a pointer and destroying it or the data it refers to. Then later, the data is not accessible.
The private ROILine* member of the View class is not set or initialized properly. Sometimes, this can lead to strange stochastic behavior; one compiled version (with the "works wonderfully block") may randomly initialize that member to be a nonzero value, while another compiled version (with one of the failing blocks) may randomly initialize that member to be zero. I've heard this referred to as a "Heisenbug" because trying to print out debugging information may change the problem.
Also, make sure you've verified that r is NULL after the line setting its value is executed. Some compilers initialize pointers to NULL and it may have not been set yet. Also check to make sure you have optimizations turned off; sometimes debuggers don't play well with optimizations, which can make a line of code execute after you think it's been executed.
The symptoms make it sound like your ROILine object has been deleted, leaving you with a dangling pointer to freed memory. When you try to call a virtual function, it crashes, because the vtable has been overwritten, but when you create a copy with the copy constructor it gets at least some valid data from the freed object, and appears to work.
I think ROILine should inherit from ROI.
Make draw virtual in ROILine and then
ROILine *r = v->ROI();
r->draw(); // debug shows r != 0x0
should work...
Connected to the problem (or not) It's a bad practice to call a function returning your ROI exactly like ROI constructor.
(referring to: ROILine* ROI() {return _roi;} //setter does some control stuff... )
Maybe the compiler gets confused...
Your copy constructor works as it takes a reference, and to do this you feed it a dereferenced (possibly null) pointer. This is one of those funny things in the language, as a reference to a dereferenced pointer doesn't actually dereference the pointer until you use the reference (C++ really is multi paradigm, it's even lazy!). Since this is undefined behavior, its only by chance that the copy constructor works at all. Its possible that in the View you've invalidated the pointer somehow.
#include <iostream>
using namespace std;
int addOne(int const & n) {
return n + 1; // Uh oh.
}
int main() {
int * ptr = 0;
cout << addOne(*ptr) << endl; // Doesn't crash here.
return 0;
}
Related
The C++ compiler I'm using is an older version (C++98 maybe?)
I can NOT dynamically allocate memory from the system pool using things like new, malloc
I can however use built-in OS calls to malloc from a heap array defined by me.
I'm running into some strange behavior (program crashes) when I do the following
class cBaseClass /* pure abstract */
{
public:
virtual void ifFunc( void ) = 0;
virtual ~cBaseClass() = 0;
}
inline cBaseClass::~cBaseClass()
{
}
class cDclass:cBaseClass
{
public:
cDclass();
~cDclass();
void ifFunc( void ); /* implement the pure virtual */
}
cDclass::cDclass( void )
{
printf("[0x%X] derived constructor called\n", this);
}
cDclass::~cDclass( void )
{
printf("[0x%X] derived destructor called\n", this);
}
void cDclass::ifFunc(void)
{
printf("[0x%X] ifFunc called from derived class\n", this);
}
uchar_t myHeap[4096];
int main ( void )
{
cDclass* pMyPtr = NULL;
uint32_t i = 0;
( void ) memset( myHeap, 0, sizeof(myHeap)/sizeof(myHeap[0]);
for( i = 0; i < 20; i++)
{
pMyPtr = myHeap[i * sizeof(cDclass) + 4];
*pMyPtr = cDclass();
pMyPtr->ifFunc(); /* Crash */
}
}
What I see is that the constructor for the derived class gets called..then its destructor gets called and then a crash.
Am I mistaken in believing that *pMyPtr = cDclass() constructs a class and then makes a copy of that class at the address specified by pMyPtr?
I say this because when I remove
pMyPtr = cDClass()
and create a dummy variable to store an instance of cDclass and then use memmove it no longer crashes.
The first weird thing is that this line:
pMyPtr = myHeap[i * sizeof(cDclass) + 4];
compiles without complaint. It's implicitly converting a uchar_t to a cDclass*, which shouldn't be possible without a reinterpret_cast. But it could be that your compiler is more lenient there. Anyway, at least you're missing a & operator here.
The second problem is that yes, you are wrong in your assumption. What the line does is construct a temporary object on the stack, then assume that at the pointer location there is already a fully constructed object, call that object's compiler-generated copy assignment operator with the temporary as an argument, then destroy the temporary.
The thing that never happens is that an object is actually constructed in the memory. This means the vptr is never initialized, so the call to the virtual function is a null dereference.
What you need to do is use placement-new to construct an object in-place. Your loop should look like this:
int main ( void )
{
uint32_t i = 0;
( void ) memset( myHeap, 0, sizeof(myHeap)/sizeof(myHeap[0]);
for( i = 0; i < 20; i++)
{
// get the address to construct the object at
uchar_t* pMyAddr = &myHeap[i * sizeof(cDclass) + 4];
// construct a new object in-place at that address
cDclass* pMyPtr = new (pMyAddr) cDclass();
pMyPtr->ifFunc(); /* Don't crash */
}
}
Note that you will be responsible for actually calling the destructor for all the objects you created.
*pMyPtr = cDclass();
Assumes that a valid object already exists at *pMyPtr and uses its assignment operator. (On a typical implementation, this is probably not good enough because it doesn't copy the vptr.)
What you need instead is
new(pMyPtr) cDclass;
to call the constructor at a specified memory location. You'll need to #include <new>.
I have a class with a static variable. Since I need a constructor that isn't the default, I'm getting a little confused, but I hope I did it well
Class
class Object3D{
public:
static Object3D ObjControl;
Object3D(); //this is here just for the initialization of the static variable
Object3D(Triangle *mesh);
Triangle *mesh;
};
At this point I need to create an Object3D and I do as below
bool Engine::OnInit() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
if((Surf_Display = SDL_SetVideoMode(WIDTH, HEIGTH, BBP, FLAGS)) == NULL) {
return false;
}
arma::colvec::fixed<3> upDirection;
upDirection << 0 << 1 << 0;
Camera cam(0.0, 0.0, 10.0, 10.0, 200.0, 90.0, upDirection);
Camera::CameraControl = cam;
arma::colvec::fixed<3> vertexA;
vertexA << -1 << 1 << 0;
arma::colvec::fixed<3> vertexB;
vertexB << 1 << 1 << 0;
arma::colvec::fixed<3> vertexC;
vertexC << 0 << -1 << 0;
Triangle tri(vertexA, vertexB, vertexC);
Triangle mesh[1];
mesh[0] = tri;
Object3D obj(mesh);
Object3D::ObjControl = obj; // PROBLEM! -> when the function extis from the OnInit ObjControl doesn't have anything inside.. it is like cleaned at the exit
return true;
}
The problem is the one that is inserted in the comment before the return.
Then when I need to pass that object to the rendering function, as below; the application closes because I'm trying to access to a location of memory not initialized
void Engine::OnRender(){
Rendering.WfRender(Object3D::ObjControl, Surf_Display, 1);
}
I think I'm doing something wrong with the static variable, but I did the same with a static variable for a Camera class, as you can see in the Engine::OnInit, and there everything works well. So I have no clue what's going on.
The main issue in your program is that you make a Triangle instance (mesh) in your function and that you pass a pointer to your static member variable ObjControl. When you leave the function, mesh is no longer available, so ObjControl points to an invalid instance. This could be solved by storing an actual Triangle instead of a pointer to a Triangle in Object3D or a container of Triangles if more are needed.
Does your Object3D class only hold onto the pointer to the mesh or take a copy of it?
Does it implement a deep-copy copy constructor?
I ask because your mesh is going out of scope after being assigned to obj, and obj is going out of scope after being assigned to the static variable. You need to either assign the mesh on the heap and hand that pointer to the static variable, or ensure the actual data is copied by correctly implementing the right constructors.
EDIT: Or, as this looks like games development, get it done quick and nasty! ;-)
Object3D::ObjControl.mesh = new Triangle(vertexA, vertexB, vertexC);
...and lose the local variables tri, mesh, and obj.
I'm a complete beginner in c++ and everything has been going on well until now. I'm new to the idea of pointers (I'm from python), and I have this weird error.
So basically, I created this "SearchNode" class, and found below is one of it's methods "getChildren" which should return a vector of other SearchNode instances, representing the possible cells to which a Knight (chessboard) could travel from it's current state. (BFS)
That said, when I finish pushing into my vector, all the elements suddenly point to 1st element only. Could someone help me out here?
PS: it's a similar problem to c++ push_back doesn't work as it is supposed ... but unlike Angela (who's was writing her own compiler), I'm a total beginner in c++. Your help with be greatly appreciated.
UPDATE
I got rid of the int*, and used array for my state. I could now successfully search the graph (therefore the states are ok) and find the shortest path, but I couldn't seem to reconstruct the path.
To test, I started at {0,0} and could find {4,4}, but the path, according to the getPath method was {4,4}, {3,6}, {3,6}, {3,6} ... (infinite loop of {3,6}). Is there something wrong with my parent pointers, or my getPath function? Thanks for your support in advance.
//Search class
class SearchNode
{
public:
//Variables
SearchNode *m_parent;
array<int,2> m_state; //I don't understand typedef's yet, will use them when I'm clearer with them :)
//Normal Constructor
SearchNode(array<int,2>& state_, SearchNode *parent_=nullptr) :
m_state(state_),
m_parent(parent_)
{}
//Method to get Next reachable states. Returns instances of SearchNode.
vector<SearchNode> getChildren()
{
int legalMoves[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
vector<SearchNode> children;
children.reserve(8);
for(int i=0; i<8; i++)
{
int x = (m_state[0] + legalMoves[i][0]);
int y = (m_state[1] + legalMoves[i][1]);
if( (x>-1) and (x<9) and (y<9) and (y>-1)) // Within the bounds of the board
{
array<int,2> childState = {x,y};
SearchNode childNode = SearchNode(childState,this);
children.push_back(childNode);
}
}
return children;
}
void getPath()
{
cout<<"\nPath: ";
cout<< this->print();
SearchNode current = *this;
unsigned int counter = 1;
while((current.m_parent!=nullptr) and counter< 10)
{
counter++;
cout<< (current.m_parent)->print();
current = *(current.m_parent);
}
cout << (current.m_parent)->print();
}
string print()
{
stringstream out;
out << "{" << this->m_state[0] << "," << this->m_state[1] << "} ";
return out.str();
}
};
Lots of mistakes and errors, I strongly suggest you turn up the warning level in your compiler so you can get more information. With GCC/G++/Clang, try "-Wall" or "-Wextra", as moshbear points out.
Your nodes never get assigned the "parent" value, you're creating a "shadow" local variable called "parent" and assigning that. To avoid common errors like this, use a prefix or postfix for member variable names to separate them from local names, e.g. "m_parent" or "_parent".
You don't assign default values in your constructor, you explicitly leave the values uninitialized.
SearchNode()
{
//do nothing
}
and then you introduce this garbage data in your pointer-based constructor, what you probably want is
SearchNode() : parent(NULL), state(NULL) {}
Your copy constructor is a disaster. You need to read up on and understand pointers and local variables.
//Start Node constructor. Still looking for an equivalent for null.
SearchNode(int *state)
{
int genericStartState[2] = {-1,-1};
SearchNode blankParent = SearchNode();
SearchNode genericStart = SearchNode(genericStartState,&blankParent);
this->parent = &genericStart;
this->state=state;
}
Firstly, "blankParent" here is a local variable containing random data because of your current copy constructor. Secondly, you're taking the address of it - of a private, local variable, which is about to stop existing when you hit the "}" at the end of the routine.
"genericStartState" is also about to go out of scope.
And aside from that, I don't think you want or need this particular constructor.
But fundamentally, the bug in your subject, is because you do the same thing in your assignment loop -- you use a temporary, local array to store the new values, and then pass a pointer to that to your constructor. Since you are taking the address, it will be the same every loop.
int childState[2] = { x, y };
SearchNode childNode = SearchNode(childState,this);
This is why all of your nodes have the same state - because they all point to the same memory location (edit: as pointed out by DyP, that side-effect isn't something you can count on, just an artefact of ordering in this case).
It might be easier for you to use simple array of ints rather than a pointer in your node structure.
Here's how the constructor side of things might look, if your compiler is VisualStudio 2012 or G++ 4.8 or Clang 4.2.
class SearchNode
{
public:
typedef std::array<int, 2> State;
private:
// I use the 'm_' convention for members, 'g_' for globals, 's_' for statics.
SearchNode* m_parent;
State m_state;
public:
//////////
// Default ctor.
SearchNode()
: m_parent(nullptr) // C++11 constant meaning pointer with value 0
, m_state({-1, -1}) // preferred but requires recent C++11 features
{
//m_state[0] = m_state[1] = -1; // had to do this instead for gcc 4.7.3
}
//////////
// Normal ctor
// I use the '_'-postfix convention for parameter names.
SearchNode(SearchNode* parent_, const State& state_)
: m_parent(parent_)
, m_state(state_)
{
}
//////////
// Copy constructor.
// We could do this, but it's the default behavior anyway.
/*
SearchNode(const SearchNode& rhs)
: m_parent(rhs.m_parent)
, m_state(rhs.m_state)
{
}
*/
// Current C++11 compilers let us be explicit and do this:
//SearchNode(const SearchNode& rhs) = default;
// But it's the default behavior so we don't have to do this one at all.
};
The latest C++11 language changes (MSVC > 2012, GCC >= 4.8, Clang >= 4.1) would allow you to replace the first two constructors with
// Kill two birds with one stone and have default parameters on our normal ctor,
// replacing both the default and normal ctor with one function.
SearchNode(SearchNode* parent_ = nullptr, const State& state_ = { -1, -1 }))
: m_parent(parent_)
, m_state(state_)
{
}
If you had a fully C++1y compatible compiler, you could boil all that down to:
class SearchNode
{
public:
typedef std::array<int, 2> State;
private:
// I use the 'm_' convention for members, 'g_' for globals, 's_' for statics.
SearchNode* m_parent = nullptr; // c++1y keyword to replace 'NULL'
State m_state = { -1, -1 };
public:
SearchNode() = default;
SearchNode(const State& rhs_) = default; // not strictly required.
SearchNode(SearchNode* parent_, const State& state_)
: m_parent(parent_), m_state(state_)
{}
};
If I place breakpoints in my destructor I notice that all the code is run through when I instantiate said object, but the lines don't have any effect (as in, the delete does not actually seem to delete the object) What is really going on here?
I am using visual studio, is this an artifact (is that the right word?) of the program?
destructor being called:
Brain::~Brain()
{
for (unsigned int i = 0; i < weapons.size(); i++)
{
delete weapons[i];
}
}
if I place breakpoints in here, they get triggered when the Brain is instantiated! and again when I close the program.
here is the objects constructor:
Brain::Brain(
int health,
Level& level,
vector<Agent>& agents,
//vector<Pickup>& pickups,
D3DXCOLOR colour,
Mesh& mesh)
: Entity(colour, mesh), gunOffset(D3DXVECTOR3(0, 0, 1.0f)),
level(level),
agents(agents),
//pickups(pickups),
colour(colour),
health(health),
enemies(vector<int>()),
seenEnemies(vector<int>()),
seenPickups(vector<int>()),
seenEnemyMarkers(vector<BoundingSphere>()),
seenPickupMarkers(vector<BoundingSphere>()),
weapons(vector<Gun*>()),
RoomKills(vector<int>()),
pathVisualisation(vector<Edge>()),
search(vector<int>()),
WALKING_INCREMENT(0.06f),
TOLERANCE(0.1f),
COMBAT_SEARCH_TIME(0),
SHOTGUN_STOPPING_DISTANCE(1.5f), PISTOL_STOPPING_DISTANCE(5.0f),
SPAWNTIME(120),
IMPACT_DISTANCE(0.6f),
FIELD_OF_VIEW(0.95f),
MARKER_SIZE(0.5f)
{
currentNodeInSearchPathInt = 0;
combatSearchCycle = 0;
spawnCycle = 0;
globalNodePositionIndex = 0;
//fightOrFlight = 0;
chosenTarget = -1;
previousTarget = -1;
pickupMemory = -1;
agentMemory = -1;
for (unsigned int i = 0; i < level.RoomCentreNodeVectors().size(); i++)
{
RoomKills.push_back(level.Nodes()[level.RoomCentreNodeVectors()[i][0]].Room());
}
weapons.push_back(new Pistol());
weapons.push_back(new Rifle());
weapons.push_back(new Shotgun());
prevTargetType = AGENT;
targetType = AGENT;
currentWeapon = PISTOL;
state = SPAWN;
}
could it have something to do with this?
for (int i = 0; i < 2; i++)
{
agents.push_back(Agent(100, *level, agents/*, level->Pickups()*/, D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f), *mesh));
}
Agent inherits from Brain.
This is Agent:
#ifndef AGENT_H
#define AGENT_H
#include <d3d10.h>
#include <d3dx10.h>
#include "Brain.h"
class level;
class Agent : public Brain
{
private:
int counter;
Level& level;
int previousState;
const int
TARGET_IS_AGENT,
TARGET_IS_OBJECT,
TARGET_IS_AGENT_MEMORY,
NO_TARGET;
int fightFlightThreshold;
const int SHOTGUN_DISTANCE_TOLERANCE;
public:
Agent(int health,
Level& level,
vector<Agent>& agents,
D3DXCOLOR colour,
Mesh& mesh);
void UpdateAgent();
void DrawAgent(D3DXMATRIX matView, D3DXMATRIX matProjection, bool dataVis);
void RegenerativeHealth();
//int TargetChooser();
};
#endif
Destructors for the object being instantiated should not be executed during that instantiation.
However, it may be that temorary objects are created as part of the process. That's the only thing I can think of that makes sense based on your description that the code is running (for the temporary objects) but not having an effect (on the object being instantiated).
This may not be too hard to check. Examint the this pointer when you're sitting at a breakpoint in the destructor then compare that with the object pointer after instantiation.
If they're the same, I'd be very surprised.
Maybe your compiled binary isn't up to date with your source code and debugger shows wrong line to be executed. This happens sometimes in Visual Studio.
If you put a breakpoint in the destructor and then look at the call stack, you will see the line that is causing the destructor to run. Almost certainly there is some copying going on and a temporary is being destructed, which is confusing you.
Debugging in release mode is sometimes tricky. The default optimization may optimize out some code so what you're stepping into in Dev studio may not match what is actually executing.
It could be that you are Debugging optimized code
When the compiler optimizes code, it repositions and reorganizes
instructions, resulting in more efficient compiled code. Because of
this rearrangement, the debugger cannot always identify the source
code that corresponds to a set of instructions.
Optimization can affect:
Local variables, which can be removed by the optimizer or moved to
locations the debugger does not understand.
Positions inside a function, which are changed when the optimizer
merges blocks of code.
Function names for frames on the call stack, which may be wrong if the
optimizer merges two functions.
So it could be that the debugger shows the instruction that it thinks is the next instruction, but actually isn't
I have an Entity class, which contains 3 pointers: m_rigidBody, m_entity, and m_parent. Somewhere in Entity::setModel(std::string model), it's crashing. Apparently, this is caused by bad data in m_entity. The weird thing is that I nulled it in the constructor and haven't touched it since then. I debugged it and put a watchpoint on it, and it comes up that the m_entity member is being changed in the constructor for std::string that's being called while converting a const char* into an std::string for the setModel call. I'm running on a Mac, if that helps (I think I remember some problem with std::string on the Mac). Any ideas about what's going on?
EDIT: Here's the code for GEntity:
GEntity::GEntity(GWorld* world, unsigned long int idNum) {
GEntity(world, idNum, btTransform::getIdentity());
}
GEntity::GEntity(GWorld* world, unsigned long int idNum, btTransform trans) : m_id(idNum), m_trans(trans), m_world(world) {
// Init unused properties
m_rigidBody = NULL;
m_entity = NULL; // I'm setting it here
m_parent = NULL;
// Find internal object name
std::ostringstream ss;
ss << "Entity" << idNum << "InWorld" << world;
m_name = ss.str();
// Create a scene node
m_sceneNode = m_world->m_sceneMgr->getRootSceneNode()->createChildSceneNode(m_name+"Node");
// Initialize the SceneNode's transformation
m_sceneNode->setPosition(bv3toOv3(m_trans.getOrigin()));
m_sceneNode->setOrientation(bqToOq(m_trans.getRotation()));
}
void GEntity::setModel(std::string model) {
m_model = model;
// Delete entity on model change
if(m_entity != NULL) { // And by the time this line comes around, it's corrupt
m_world->m_sceneMgr->destroyEntity(m_entity);
m_entity = NULL;
}
// Create new entity with given model
m_entity = m_world->m_sceneMgr->createEntity(m_name+"Ent", model);
// Apply a new rigid body if needed
if(m_rigidBody != NULL) {
initPhysics();
}
}
void GEntity::initPhysics() {
deinitPhysics();
}
void GEntity::deinitPhysics() {
if(m_rigidBody != NULL) {
m_world->m_dynWorld->removeRigidBody(m_rigidBody);
delete m_rigidBody;
m_rigidBody = NULL;
}
}
And here's the definition of GEntity:
class GEntity : public btMotionState {
public:
GEntity(GWorld* world, unsigned long int idNum);
GEntity(GWorld* world, unsigned long int idNum, btTransform trans);
void setModel(std::string modelName);
void initPhysics();
void deinitPhysics();
void getWorldTransform(btTransform& worldTrans) const;
void setWorldTransform(const btTransform &trans);
void parent(GEntity* parent);
protected:
unsigned long int m_id;
// Physics representation
btTransform m_trans;
btRigidBody* m_rigidBody;
// Graphics representation
Ogre::SceneNode* m_sceneNode;
Ogre::Entity* m_entity;
// Engine representation
GWorld* m_world;
GEntity* m_parent;
std::string m_name;
std::string m_model; // Used to find physics collision mesh
};
And here's the code calling setModel:
// Setup game world
GWorld* world = new GWorld(win);
GEntity* ent = world->createEntity();
ent->setModel(std::string("Cube.mesh"));
Your problem is that this line is constructing a nameless temporary GEntity inside the constructor body for a different GEntity. The temporary is then thrown away once the statement completes and no further initialization of the non-temporary GEntity is performed.
GEntity(world, idNum, btTransform::getIdentity());
If you want to share some initialization code between your two constructors you should create a member function that performs the required actions and call this function from both constructors. C++ doesn't (currently) allow you to delegate initialization from one constructor to a different constructor or call two constructors on the same object.
My best guess is that the problem is in GWorld::createEntity. If you're creating a local GEntity on the stack and returning a pointer to it, you'll see something like what you describe, as the GEntity is destroyed when GWorld::createEntity returns and the memory is reused for the temp string constructed to pass to setModel
Edit
I see you've added more code, including the definition of createEntity. That looks fine, but I would still suggest looking for some way in which the GEntity you're seeing the problem with gets deleted (and the memory reused for a string) before you call setModel.
One solution I have found is to use string.resize(n), which will resize the function. However, I do not know why this works, and I feel my problem is with my code since std::string is part of the standard C++ library.
I can't find the answer but I can make a suggestion that will help catch the problem:
Add assertions. A lot of assertions. Each one of those functions really need some assertions at least at their beginning. That will certainly help you catch wrong states early.
And by the way, you should use a constant reference as parameter of your setModel() function.
In C++ you can not call a constructor from within a constructor.
Try
GEntity::GEntity(GWorld* world, unsigned long int idNum) : GEntity(world, idNum, btTransform::getIdentity() {}