Pergunta

I got an issue here that is strange to me, I purposely changed my program such that it uses dynamic memory, because I was getting stack over errors before. The memory intensive parts got changed to dynamic, but I am still getting stack overflow, while I would expect heap overflow, but I have more than enough RAM so even those shouldn't be happening.

Header file:

#ifndef __FPS_h_
#define __FPS_h_

#include "BaseApplication.h"

#include <Ogre/OgreLogManager.h>
#include <Ogre/OgreInstanceManager.h>

#include <btBulletDynamicsCommon.h>
#include <btIDebugDraw.h>

#include "BtOgreExtras.h"
#include "BtOgreGP.h"
#include "btOgrePG.h"

class FPS : public BaseApplication
{
public:
    FPS(void);
    virtual ~FPS(void);

protected:
    virtual void createScene(void);
    virtual void createCamera(void);
    virtual void createViewports(void);

    virtual bool frameRenderingQueued(const Ogre::FrameEvent &evt);

    void initializePhysics(void);
    void initializeGraphics(void);
    void initializeGraphicsBase(void);
    void initializeGraphicsGround(void);
    void initializeGraphicsTiles(void);
    void initializeGraphicsRobot(void);

private:
    Ogre::InstanceManager* tileInstanceManager;
    Ogre::SceneNode*** tileSceneNode[300][300];
    btRigidBody*** tileRigidBody[300][300];
    //Ogre::SceneNode* tileSceneNode;
    //btRigidBody* tileRigidBody;

    Ogre::SceneNode* robotSceneNode;
    btRigidBody* robotRigidBody;

    btDiscreteDynamicsWorld* dynamicsWorld;
    BtOgre::DebugDrawer* debugDrawer;
};

#endif // #ifndef __FPS_h_

Part of the source file:

void FPS::initializeGraphicsTiles() {
    //tile instance manager
    uint16_t flags = Ogre::InstanceManagerFlags::IM_USEALL;
    tileInstanceManager = mSceneMgr->createInstanceManager("InstanceManager", "tile.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::HWInstancingVTF, 400, flags);

    //fake tile
    Ogre::Entity* entFakeTile = mSceneMgr->createEntity("Tile", "tile.mesh");

    //initialize arrays
    **tileSceneNode = new Ogre::SceneNode**[300];
    **tileRigidBody = new btRigidBody**[300];

    //tile
    for (int x = 0; x <= 300; x++) {
        *tileSceneNode[x] = new Ogre::SceneNode**[300];
        *tileRigidBody[x] = new btRigidBody**[300];
        for (int z = 0; z <= 300; z++) {
            Ogre::InstancedEntity* entTile = tileInstanceManager->createInstancedEntity("Examples/Instancing/VTF/HW/Robot");
            entTile->setCastShadows(true);

            Ogre::SceneNode* tempNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
            tempNode->attachObject(entTile);
            **tileSceneNode[x][z] = tempNode;   

            BtOgre::StaticMeshToShapeConverter converter(entFakeTile);
            btConvexHullShape* mShape = converter.createConvex();
            btScalar mass = 100;
            btVector3 inertia;
            BtOgre::RigidBodyState* state = new BtOgre::RigidBodyState(tempNode);
            btRigidBody* tempBody = new btRigidBody(mass, state, mShape, inertia);

            btTransform originalTransform;
            tempBody->getMotionState()->getWorldTransform(originalTransform);
            btVector3 originalOrigin = originalTransform.getOrigin();
            originalOrigin.setX(originalOrigin.getX() + (x * 10.0));
            originalOrigin.setZ(originalOrigin.getZ() + (z * 10.0));
            originalTransform.setOrigin(originalOrigin);
            tempBody->getMotionState()->setWorldTransform(originalTransform);

            dynamicsWorld->addRigidBody(tempBody);
            **tileRigidBody[x][z] = tempBody;
        }
    }
}

If I remove (or drastically reduce) the double array, then the errors are gone.

EDIT: I know I am not cleaning up memory yet, first want to get the application actually running.

Foi útil?

Solução

Check out sizeof(FPS). I would guess it's quite large (>1MB) and you are allocating an instance of FPS itself on the stack, right? Where you use FPS app;, replace it with std::unique_ptr<FPS> app_ptr( new FPS );, that should solve your problem.

Outras dicas

The size of FPS structure is about 1.4 MiB (sizeof(void *) * 2 * 300 * 300), and if you are realy needing 2D arrays of pointers to pointer to pointer to a class, I am suspecting bad design decisions.

Using std::vector< std::vector< Ogre::SceneNode > > tileSceneNode; instead should greatly reduce your troubles with memory

I think you've got a little confused. This first line declares a 300x300 array of pointer-to-pointer-to-pointer-to tileRigidBody.

btRigidBody*** tileRigidBody[300][300]; 

So, you have 90,000 3* pointers. But, you then try doing stuff like this, which is assuming you have one pointer to 300 pointers to 300 pointers...

**tileRigidBody = new btRigidBody**[300];

for (int x = 0; x <= 300; x++) {
    *tileSceneNode[x] = new Ogre::SceneNode**[300];
    *tileRigidBody[x] = new btRigidBody**[300];

Use std::vector<> instead, and things will become a lot clearer!

If you must do it with arrays (sigh...) then start with something like this:-

btRigidBody** tileRigidBody[300];  // 300 pointers to dynamic arrays 

Your 'init' then looks like this (ignoring the sceneNode stuff, which is similar):-

for (int x = 0; x < 300; x++) 
{
    tileRigidBody[x] = new btRigidBody*[300]; // create array of 300 pointers.
    for (int z = 0; z < 300; z++) 
    {
        ....
        btRigidBody* tempBody = new btRigidBody(mass, state, mShape, inertia);
        tileRigidBody[x][z] = tempBody;
    }

Note the change in the for loops to be < 300 - your code is overflowing the array.

Warning - code not tested, but you should get the idea.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top