5

几乎每次我跳回 C 项目时,我都会把它搞砸。尝试访问结构中的结构时出现段错误。假设我有以下(简化的)游戏结构:

struct vector {
    float x;
    float y;
};

struct ship {
    struct vector *position;
};

struct game {
    struct ship *ship;
} game;

还有一个初始化船的函数:

static void
create_ship(struct ship *ship)
{
    ship = malloc(sizeof(struct ship));
    ship->position = malloc(sizeof(struct vector));
    ship->position->x = 10.0;
}

然后在 main() 中:

int main() {
    create_ship(game.ship);
    printf("%f\n", game.ship->position->x); // <-- SEGFAULT
}
4

3 回答 3

10

您是game.ship按值传递的,因此create_ship变量内部ship只是该指针的副本,它只是更改了副本。当函数返回时,指向你malloced 的指针丢失并且函数的效果在它之外不可见,除了内存泄漏。

您需要将指针传递给指针并game.ship通过它进行修改:

static void
create_ship(struct ship **ship)
{
    *ship = malloc(sizeof(struct ship));
    (*ship)->position = malloc(sizeof(struct vector));
    (*ship)->position->x = 10.0;
}

create_ship(&game.ship);

或者,也许更好的方法是按照 Johnny Mopp 在评论中建议的那样,从函数返回指针,而不是修改它之外的指针:

static struct ship* create_ship()
{
    struct ship* s = malloc(sizeof(struct ship));
    s->position = malloc(sizeof(struct vector));
    s->position->x = 10.0;

    return s;
}

game.ship = create_ship();

当然,你所malloc编辑的,不要忘记free.

于 2012-10-02T17:07:41.957 回答
2

您应该通过引用传递:

static void create_ship(struct ship **ship);

create_ship(&game.ship);

否则分配的结构将被丢弃。

于 2012-10-02T17:07:52.130 回答
1

您的create_ship函数实际上并没有改变game.ship,因为参数是按值传递的。在该create_ship函数中,仅更改了一个副本。所以在调用之后,game.ship保持未初始化(或者NULL,或者调用之前的任何值)。因此,您也会丢失对新分配的船的引用,并泄漏内存。

您需要将指针传递给指针才能更改它:

static void create_ship(struct ship **ship)
{
    *ship = malloc(sizeof(struct ship));
    // ...

在通话中:create_ship(&game.ship);

您还可以选择将新船作为函数返回值传递:

static ship *create_ship()
{
    struct ship *ship = malloc(sizeof(struct ship));
    // ...

    return ship;
}

// ...

game.ship = create_ship();
于 2012-10-02T17:07:50.443 回答