5

私は、C プロジェクトに戻るたびに、これをやめます。構造内の構造にアクセスしようとすると、segfault が発生します。ゲームに次の(単純化された)構造があるとしましょう:

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はそのポインターのコピーにすぎず、コピーを変更するだけです。関数が戻ると、malloc編集した内容へのポインターが失われ、メモリ リークを除いて、関数の効果はその外部には表示されません。

ポインターにポインターを渡し、それを変更する必要があります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

You should pass by reference:

static void create_ship(struct ship **ship);

and

create_ship(&game.ship);

otherwise the allocated structure is discarded.

于 2012-10-02T17:07:52.130 に答える
1

引数が値渡しcreate_shipであるため、関数は実際には変更されていません。関数では、コピーのみが変更されています。したがって、呼び出しの後、初期化されていないままになります(または、または呼び出し前の値は何でも)。その結果、新しく割り当てられたシップへの参照も失われ、メモリ リークが発生します。game.shipcreate_shipgame.shipNULL

ポインターを変更するには、ポインターをポインターに渡す必要があります。

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 に答える