1

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.

5
  • Have you tried a debugger? What's the result? Commented Oct 21, 2013 at 19:06
  • @MM. Unhandled exception at 0x00007FF7AC19C857 in FPS.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000B5ABDC3000). before it enters the main. Commented Oct 21, 2013 at 19:08
  • 1
    This isn't the problem, but names that contain two consecutive underscores (__FPS_h_) and names that begin with an underscore followed by a capital letter are reserved to the implementation. Don't use them. Commented Oct 21, 2013 at 19:36
  • <=300 is wrong too: that will write 301 elements... Commented Oct 21, 2013 at 19:56
  • @Roddy Fixed that, it was actually a big error. It now gives some error about **tileSceneNode[x][z] = tempNode; Commented Oct 21, 2013 at 20:21

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

The main starts with FPS app; indeed, trying to get the size now.
I am using std::cout << "Size: "<< sizeof(FPS); as first line after the main, but still gives a stackoverflow before printing anything, is that normal?
@skiwi Yes, that is normal as the compiler is trying to reserve stack space for FPS app; even if it comes afterwards. Change it to the std::unique_ptr<FPS> app_ptr(...) and you will see the output from the first line.
1

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

Comments

1

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.

1 Comment

I find arrays more neat though, except that... they are not. In any case, could you point me how I should do it with arrays?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.