std :: string构造函数会破坏指针

时间:2010-03-14 21:48:57

标签: c++ string macos memory-corruption

我有一个Entity类,它包含3个指针:m_rigidBody,m_entity和m_parent。在Entity :: setModel(std :: string model)的某个地方,它正在崩溃。显然,这是由m_entity中的错误数据引起的。奇怪的是,我在构造函数中将其弄糊涂了,从那时起就没有碰过它。我调试了它并在其上放置了一个观察点,并且发现m_entity成员正在std :: string的构造函数中被更改,这是在将const char *转换为用于setModel调用的std :: string时被调用的。我在Mac上运行,如果这有帮助(我想我记得Mac上的std :: string有些问题)。关于发生了什么的任何想法?

编辑:这是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;
    }
}

以下是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
};

这是调用setModel的代码:

// Setup game world
GWorld* world = new GWorld(win);
GEntity* ent = world->createEntity();
ent->setModel(std::string("Cube.mesh"));

6 个答案:

答案 0 :(得分:5)

你的问题是这一行是在构造函数体内为另一个GEntity构建一个无名的临时GEntity。一旦语句完成,临时就会被丢弃,并且不会进一步初始化非临时GEntity。

GEntity(world, idNum, btTransform::getIdentity());

如果要在两个构造函数之间共享一些初始化代码,则应创建一个执行所需操作的成员函数,并从两个构造函数中调用此函数。 C ++(目前)不允许您将初始化从一个构造函数委托给另一个构造函数,或者在同一个对象上调用两个构造函数。

答案 1 :(得分:2)

我最好的猜测是问题出在 GWorld :: createEntity 中。如果你在堆栈上创建一个本地 GEntity 并返回一个指向它的指针,你会看到类似于你所描述的内容,因为 GEntity GWorld :: createEntity 返回并且内存被重用于构造为传递给 setModel 的临时字符串

修改

我发现您添加了更多代码,包括 createEntity 的定义。这看起来很好,但我仍然建议在调用setModel之前寻找一些方法,在这种方式中,你看到问题的GEntity会被删除(并且内存重用于字符串)。

答案 2 :(得分:1)

我找到的一个解决方案是使用string.resize(n),这将调整函数的大小。但是,我不知道为什么会这样,我觉得我的问题出在我的代码上,因为std::string是标准C ++库的一部分。

答案 3 :(得分:0)

我找不到答案,但我可以提出一个有助于解决问题的建议:

添加断言。很多断言。这些功能中的每一个至少在开始时都需要一些断言。这肯定会帮助你尽早赶上错误的状态。

顺便说一下,你应该使用常量引用作为setModel()函数的参数。

答案 4 :(得分:0)

在C ++中,你不能从构造函数中调用构造函数。

答案 5 :(得分:0)

尝试

GEntity::GEntity(GWorld* world, unsigned long int idNum) : GEntity(world, idNum, btTransform::getIdentity() {}