K. Russell Smith
K. Russell Smith

Reputation: 183

Irregular behavior in C physics program

I'm trying to put together a simple physics engine:

#include <stdio.h>
typedef struct Vector
{
    double x, y;
} Vector;

const double GRAVITY  = 0.1;
const double FRICTION = 0.9;

typedef struct RigidBody
{
    Vector*  pos;
    Vector*  vel;
    Vector*  acc;
    uint16_t mass;
} RigidBody;

void addForce(RigidBody* body, double x, double y)
{
    body->acc->x += x / body->mass;
    body->acc->y += y / body->mass;
}
void updateRigidBody(RigidBody* body)
{
    addForce(body, 0, GRAVITY * body->mass);
    
    body->vel->x += body->acc->x;
    body->vel->y += body->acc->y;
    
    body->vel->x *= FRICTION;
    body->vel->y *= FRICTION;
    
    body->pos->x += body->vel->x;
    body->pos->y += body->vel->y;
    
    body->acc->x = 0;
    body->acc->y = 0;
}
void resetRigidBody(RigidBody* body, double x, double y)
{
    body->pos->x = x;
    body->pos->y = y;
    
    body->vel->x = 0;
    body->vel->y = 0;
    
    body->acc->x = 0;
    body->acc->y = 0;
}

struct
{
    RigidBody body;
} Player;

void initPlayer(double x, double y)
{
    Player.body = (RigidBody)
    {
        &((Vector) {x, y}),
        &((Vector) {0, 0}),
        &((Vector) {0, 0}),
        10,
    };
}
void updatePlayer()
{
    updateRigidBody(&Player.body);
}
void resetPlayer(double x, double y)
{
    resetRigidBody(&Player.body, x, y);
}

int main()
{
    initPlayer(10, 10);
    {
        int i;
        for (i = 0; i < 10; ++i)
        {
            updatePlayer();
        }
    }
    printf("%g", Player.body.pos->y);
    return 0;
}

Unfortunately, it does not print the expected result, and instead prints 0.99. I tried to diagnose it by printing the rigidbody's Y speed after updating it, by adding this after line 42:

    printf("%g\n", body->vel->y);

Unfortunately, that actually changed the result:

0.99
0.99
0.99
0.99
0.99
0.99
0.99
0.99
0.99
0.99
4.16586e-312

This would seem to suggest a memory problem possibly caused by undefined behavior, but looking at my code everything seems regular, and my compiler did not issue any warnings; I also avoided allocating any memory (e.g. using malloc), and relied on the stack. What's wrong with my code? Thank you.

Upvotes: 3

Views: 89

Answers (1)

M.M
M.M

Reputation: 141638

In this code:

Player.body = (RigidBody)
{
    &((Vector) {x, y}),
    &((Vector) {0, 0}),
    &((Vector) {0, 0}),
    10,
};

there are compound literals at block scope, which means their lifetime ends after the current block. When the function returns, the object body contains dangling pointers.

It would be much simpler to just not use pointers:

typedef struct RigidBody
{
    Vector pos, vel, acc;
    uint16_t mass;
} RigidBody;

// ...

Player.body = (RigidBody)
{
    .pos.x = x,
    .pos.y = y,
    .mass = 10
};

Upvotes: 3

Related Questions