Reputation: 69269
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.
Upvotes: 1
Views: 570
Reputation: 68033
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.
Upvotes: 1
Reputation: 3423
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
Upvotes: 1
Reputation: 56863
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.
Upvotes: 3