c++stack-overflowbox2d

Box2D: Encountered C6262 Warning "Function uses '103820' bytes of stack. Consider moving some data to heap." on main()


I encountered this warning

Warning C6262: "Function uses '103820' bytes of stack. Consider moving some data to heap."

while I was trying out Box2D version 2.4.1 on Visual Studio 2022.
This warning was highlighted on my main function:

#include <box2d/box2d.h>
#include <cstdio>

// initialize gravity vector
const b2Vec2 GRAVITY(0.f, -10.f);

int main() {
    // create new world
    b2World world(GRAVITY);

    // define ground box 
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0.f, -10.f);

    // set ground to be a rigid body so that it is immovable
    b2Body* groundBody = world.CreateBody(&groundBodyDef);

    // sets shape of the ground to be rectangular
    // length of groundBox is 100 units
    // height of groundBox is 20 units
    b2PolygonShape groundBox;
    groundBox.SetAsBox(50.f, 10.f);

    // bind ground shape to ground rigid body
    groundBody->CreateFixture(&groundBox, 0.f);

    // define dynamic body 
    // setting type to dynamic body allows it to move
    // in response to forces
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(0.f, 4.f);
    b2Body* body = world.CreateBody(&bodyDef);

    // set shape of the dynamic box to be a square
    // size is 2 units
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(1.f, 1.f);

    // define a fixture for the dynamic box
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox;
    fixtureDef.density = 1.f;
    fixtureDef.friction = 0.3f;

    // bind fixture to dynamic body
    body->CreateFixture(&fixtureDef);

    // declare time step
    // at each time step, the engine will do the physics math 
    // (it's like calculating each point on the graph)
    const float TIME_STEP = 1.f / 60.f;

    // declare number of iterations to iterate
    // all constraints to achieve accurate results
    const int32 VELOCITY_ITERATIONS = 6;
    const int32 POSITION_ITERATIONS = 2;

    // begin simulation loop

    for (int32 i = 0; i < 60; i++) {
        world.Step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);

        b2Vec2 position = body->GetPosition();
        float angle = body->GetAngle();

        printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
    }

    world.DestroyBody(body);
    world.DestroyBody(groundBody);
    body = NULL;
    groundBody = NULL;

    return 0;
}

It is worth pointing out that the warning message appeared when I opened the solution of this project today. The message did not appear yesterday when I was checking if this message appear after executing the code several times.

This isn't the first time I encountered this warning, as I also faced this warning when using the same version of Box2D for the first time when I was following the HelloBox2D tutorial in the docs. The code snippet above is in fact the result upon following the tutorial. The same warning also appeared when I implemented Box2D on my C++ game (which I'm currently working on). So far, the code didn't result in any crashes, but I have a feeling it might crash eventually when I keep on adding more bodies.

I tried increasing the stack commit size and stack reserve size to 1048576 and 2097152, but it didn't suppress the error. I'm assuming that this error was caused by the b2World world object since having that line alone used 103288 bytes.

This has been bugging me for a couple of days, so is it best to just ignore this warning?
If not, how should I address this?


Solution

  • You should definitely not ignore the warning.

    The stack it typically rather small and placing a large object on it will get you into a risk of a stack-overflow from which the program will not be able to recover.
    The fact that at the moment the program behaves OK is not relevant. It could happen whenever you do some code modifications that will change the stack usage implicitly (e.g. decare some more local variables, use deeper function call nesting etc.).

    You should identify the big object and place it on the heap instead, as suggested.

    The simplest would be to new it (and delete before the program exits).
    But manual memory management is not recommended in modern C++.
    You should use a smart pointer instead.

    Assuming the object is b2World world (as you suspect), you can use std::unique_ptr (with std::make_unique) as shown below:

    #include <memory>   // required for std::unique_ptr
    
    // ...
    
    std::unique_ptr<b2World> pWorld = std::make_unique<b2World>(GRAVITY);
    b2World & world = *pWorld;
    

    Notes:

    1. The last line is only needed if you want to keep the rest of your code as is. You can use pWorld directly, but instead of using . to access the members, use ->.

    2. If the object must be shared, you can use std::shared_ptr (with std::make_shared), instead of std::unique_ptr.


    As mentioned below in a comment, there is another option, given that world is by nature a global object:
    Make it a global variable by moving it before main and it will no longer be placed on the stack.
    Keep in mind though that globals of any kind are considered bad practice to some extent.
    You can also encapsulate it in a Singleton (although it can be argues that singleton are no better than globals).