C物理程序中的不规则行为

Irregular behavior in C physics program

提问人:K. Russell Smith 提问时间:6/26/2020 最后编辑:K. Russell Smith 更新时间:6/26/2020 访问量:82

问:

我正在尝试将一个简单的物理引擎组合在一起:

#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;
}

不幸的是,它不会打印预期的结果,而是打印 0.99。我试图通过在更新刚体后打印刚体的 Y 速度来诊断它,方法是在第 42 行之后添加以下内容:

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

不幸的是,这实际上改变了结果:

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

这似乎表明内存问题可能是由未定义的行为引起的,但从我的代码来看,一切似乎都很正常,我的编译器没有发出任何警告;我还避免分配任何内存(例如使用 malloc),而是依赖堆栈。我的代码有什么问题?谢谢。

C 内存

评论

6赞 Shawn 6/26/2020
您正在设置为返回后不再存在的值的地址Player.bodyInitPlayer()
3赞 stark 6/26/2020
有什么理由要指点?为什么不在 RigidBody 中只包含 Vectors?
0赞 Jerry Jeremiah 6/26/2020
@JohnBollinger 哎呀!我误读了标签。

答:

3赞 M.M 6/26/2020 #1

在此代码中:

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

块范围内有复合文字,这意味着它们的生存期在当前块之后结束。当函数返回时,该对象包含悬空指针。body

不使用指针会简单得多:

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

// ...

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