【问题标题】:Visual Studio watch shows different values for same objectVisual Studio 监视显示同一对象的不同值
【发布时间】:2015-05-23 19:54:52
【问题描述】:

我正在和其他几个学生一起开发一个游戏,但我遇到了一个问题。 我有一个工厂对象,它有一个名为registeredObjectsstd::vector<BehaviourFactoryCallbackObject>BehaviourFactoryCallbackObject 包含用于创建对象的用户给定函数。 此部分位于游戏引擎 (irrlicht) 创建的 .dll 中。

在游戏中,我从这个工厂创建了一个对象,并注册了一些用于创建对象的函数。

然后引擎(.dll)使用这个工厂。

问题是功能似乎没有正确注册,而(根据 Visual Studio 的手表)同时它确实注册了。

我如何初始化工厂和注册函数:

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

如果我按照这个进入工厂内部,那么新的 BehaviourFactoryCallbackObject 会正确添加到 registeredObjects(根据 Visual Studio 的手表)。但是,一旦我离开该函数,registeredObjects 的大小就会调整回 0。 在某个时刻,大小变为 1,但第 0 个元素包含一个无效地址作为其成员(而不是预期的函数指针)。

factory 曾经是智能指针的一部分。我将其更改为普通指针,希望可以解决此问题。除此之外,我尝试在 google/stackoverflow 上进行搜索,但我不知道要搜索什么。

我的问题:有没有人知道可能是什么问题并知道如何解决它?

工厂必须在游戏引擎中,我的游戏中的代码必须在游戏中。 我用手表试过的东西: 观看factory 并折叠它。 观看factory->RegisteredObjects.size()。 我试图查看 RegisteredObjects 它的地址,但失败了。 如果RegisteredObjects 的地址更改了 4 个或更多字节,我添加了一个断点。没有发生中断(添加元素后除外)。

附加代码:

//.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));
}

如果您需要任何其他信息,请说出来。

编辑

一步一步的位置

下面的手表报告都检查相同的向量
我开始游戏,它创建了一个工厂。
我使用RegisterBehaviour(pID, pFP)向这个工厂注册了一个函数
游戏步入函数并在向量中推送BehaviourFactoryCallbackObject
Watch 报告矢量大小为 1
跳出函数,watch 报告向量大小为 0
向工厂注册一个新函数,再次单步执行该函数
立即观看报告大小为 1
新对象被推送,Watch 现在报告大小为 2
再次走出去,watch 报告大小为 0
注册新函数,进入函数
立即观看报告大小为 2
再次推送新对象,watch 报告大小为 3
走出去,再次观看大小为 0 的报告
完成注册,继续..

稍后我们实际使用工厂
此时手表报告大小为 1
第 0 个元素的 fp 的地址无效,id 的地址很大。
调试器因错误的 aloc 异常而中断。

【问题讨论】:

  • 离题:通常以小写开头的成员。一些风格指南甚至使用 m_ 作为前缀。
  • 我同意。我自己没有写工厂,但它是我调试任务的一部分。我将编辑问题以使其更具可读性。

标签: c++ visual-studio-2012


【解决方案1】:

您的问题没有提供足够的信息,因此很难写出准确的答案。说了这么多,我说说我的想法:

我怀疑就行了:

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

我一直对temporary objects 持怀疑态度。

试试:

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

我在另一个帖子中看到VS2012 might have a bug on move semantics

您还可以进行以下测试:

BehaviourFactoryCallbackObject 实现一个析构函数并在其中设置一个断点,并观察被调用的析构函数。如果调用了析构函数,那么当执行流程超出函数范围时,临时对象正在被销毁。

【讨论】:

  • 嗯,你肯定发现了一个会引起很多头痛的问题。我实施了您的解决方案(并且正在打我的额头)。然而问题仍然存在。我会写下正在发生的情况,也许会提供更多信息。
【解决方案2】:

最终解决了。 包含工厂的对象被删除,后来像这样使用:

if (delete)
    delete object;

//Some code..

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

所以我是愚蠢的。

情况仍然很奇怪,我通过使用不同的编译器(甚至是不同的 IDE,在本例中为 xcode)发现了这个问题。这个调试器它的手表没有出错,因此更容易找到问题。

【讨论】:

  • 未定义未定义
  • Undefined 据我所知,不包括标题或任何其他类型的定义(类、函数)。这是调试器(或观察者)向我显示错误信息是 VS 但在 XCode 中正确信息的情况。
  • 未定义行为 - 使用释放的内存
  • 没错,但问题中写的情况是在使用释放内存之前。问题中没有很好地描述它,但当时它似乎不是问题的一部分。它仍然没有,因为它发生在释放内存之前。哦,好吧...
猜你喜欢
  • 2013-05-10
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多