RdeGier
RdeGier

Reputation: 26

Visual Studio watch shows different values for same object

I am working on a game with a few other students and I just encountered an issue. I have a factory object which has a std::vector<BehaviourFactoryCallbackObject> called registeredObjects. BehaviourFactoryCallbackObject contains a user given function used to create objects. This section is in the .dll created by the game engine (irrlicht).

Inside the game I create an object out of this factory and I register some functions to use for creating objects.

Then the engine (.dll) uses this factory.

The issues is that the functions do not seem to register properly, while (according to visual studio's watch) at the same time it does register properly.

How I initialise the factory and register functions:

//This part is in the game, not the .dll
factory = new irr::AI::BehaviourFactory();
factory->RegisterBehaviour(ePID_SomeID, SomeBehaviour::GetInstance);

If I follow this to inside factory then the new BehaviourFactoryCallbackObject gets properly added to registeredObjects (according to visual studio's watch). However once I leave the function the size of registeredObjects is adjusted back to 0. At some point the size changes to 1, but the 0th element contains an invalid address as its member (instead of an expected function pointer).

factory used to be part of a smart pointer. I changed it to a normal pointer hoping that would fix this. Besides that I tried searching on google/stackoverflow but I have no idea what to search for.

My question: does anyone have an idea of what could be the issue and know how to possibly solve it?

The factory is required to be in the game engine and the code in my game has to be in the game. Things I tried with watch: Watch factory and collapse it. Watch factory->RegisteredObjects.size(). I tried to watch RegisteredObjects its address, but failed at it. I added a breakpoint if the address of RegisteredObjects changed by 4 or more bytes. No breaks happened (except once you add an element).

Additional code:

//.h file, everything in this snippit is in the .dll
typedef IBehaviour* (* GetBehaviourCallBack) (void);

class BehaviourFactoryCallbackObject
{
public:
    BehaviourFactoryCallbackObject(int pID, GetBehaviourCallBack pFP) : id(pID), fp(pFP) { }
    int GetID();
    IBehaviour* BuildBehaviour();
private:
    GetBehaviourCallBack fp;
    int id;
};

class BehaviourFactory
{
public:
    BehaviourFactory(void) { }
    void RegisterBehaviour(int pID, GetBehaviourCallBack pFP);
    IBehaviour* GetBehaviour(int pID);
private:
    std::vector<BehaviourFactoryCallbackObject> registeredObjects;
};

//.cpp file
void BehaviourFactory::RegisterBehaviour(int pID, GetBehaviourCallBack pFP)
{
    //This vector does what I expect it to do but only when I am 
    //inside this function with the debugger
    registeredObjects.push_back(BehaviourFactoryCallbackObject(pID,pFP));
}

If you need any additional information then please say so.

EDIT

Step by step sitation

The watch reports below all check the same vector
I start the game and it creates a factory.
I register a function to this factory using RegisterBehaviour(pID, pFP)
Game steps in the function and pushes a BehaviourFactoryCallbackObject in the vector
Watch reports a vector size of 1
Step out of function, watch reports a vector size of 0
Register a new function to the factory, stepping in the function again
Watch now reports a size of 1
New object is pushed and Watch now reports a size of 2
Step out again, watch reports a size of 0
Register new function, step in the function
Watch now reports a size of 2
New object pushed again, watch reports a size of 3
Step out and yet again watch reports a size of 0
Done registering, continue..

Moments later we actually use the factory
At this point watch reports a size of 1
0th element has an invalid address for fp and a huge negative number for id.
Debugger breaks with a bad aloc exception.

Upvotes: 0

Views: 140

Answers (2)

RdeGier
RdeGier

Reputation: 26

Well solved it eventually. The object containing the factory was deleted and later on used like this:

if (delete)
    delete object;

//Some code..

return new fooObject(.., .., object->factory, ..);

So I was being stupid.

The situation is still weird and I found this issue by using a different compiler (and even a different IDE, xcode in this case). This debugger its watch did not bug out, making it easier to find the issue.

Upvotes: 0

Raydel Miranda
Raydel Miranda

Reputation: 14360

Your question don't give enough information and that makes harder to write an accurate answer. Said this, I'll tell what I think:

I suspect on the line:

registeredObjects.push_back(BehaviourFactoryCallbackObject(pID,pFP));

I always have suspicious about temporary objects.

Try:

BehaviourFactoryCallbackObject BFC(pID,pFP);
registeredObjects.push_back(BFC);

I have read in another thread that VS2012 might have a bug on move semantics.

You can also make the following test:

Implement a destructor for BehaviourFactoryCallbackObject and set a breakpoint in it, and watch for the destructor being called. If the destructor gets called, then the temporary object is being destroying when the execution flow gets out the function scope.

Upvotes: 1

Related Questions