释放传递给函数的内存

时间:2018-09-22 13:30:08

标签: c memory-management

我目前正在构建一组结构,用于存储Uno游戏的状态。游戏存储在包含以下数据的结构中。我用称为Deck的结构代表一副纸牌,该结构将像这样定义的堆栈进行操作:

typedef struct _card *Card;
typedef struct _deck *Deck;
typedef struct _listCard *ListCard;
typedef struct _player *Player;

struct _card {
    value value;
    color color;
    suit suit;
};

struct _listCard {
    Card card;
    ListCard next;
};

struct _player {
    // Integer between 0 and 3.
    int player_id;
    //  Player has a hand (a deck of cards)
    Deck hand;
};

// A deck is an ADT for a linked lis of ListCards.
struct _deck {
    // Keep track of the deck.
    int num_cards;

    // Stack of cards in the deck.
    // Keep track of the top of the deck
    ListCard top;
};

struct _gamestate {
    int curr_player;
    int turn_number;
    Card curr_card;
};

struct _game {
    Deck draw_pile;
    Deck discard_pile;
    Player players;
    GameState game_state;
    int turnNumber;
    int deckSize;
};

我已经实现了很多功能,现在正在尝试编写一个将删除卡片组的功能。

static void freeDeck(Deck deck) {
    ListCard curr = deck->top;
    if (curr == NULL) {
        free(deck);
        return;
    }
    while (curr != NULL) {
        ListCard temp = curr;
        destroyCard(temp->card);
        curr = curr->next;
        free(temp);
    }
    free(deck);
}

void destroyCard(Card card) {
    free(card);
}

现在,我遇到的问题是实现弹出功能,并使用该功能的返回值将卡从一个牌组移到另一个牌组(例如拿走牌组的顶牌并将其放在弃牌堆中)。

static Card popCard(Deck deck) {
    // sanity check
    if (deck == NULL) {
        return NULL;

    // Can't pop from an empty stack.
    } else if (deck->top == NULL) {
        return NULL;

    // Only one card in the deck.
    } else if (deck->top->next == NULL) {
        Card temp = deck->top->card;
        free(deck->top);
        deck->top = NULL;

        return temp;
    }
    // Otherwise: at least two cards in the deck:

    Card val = deck->top->card;
    ListCard temp = deck->top->next;
    free(deck->top);
    deck->top = temp;
    return val;
}

这是我要弹出的功能,这是我要添加的功能:

static void addToDeck(Deck deck, Card card) {
    if (deck->top == NULL) {
        deck->top = newListCard(card);
    } else {
        addCard(deck, card);
    }
    deck->num_cards++;
}

static ListCard newListCard(Card card) {
    ListCard newCard = malloc(sizeof(struct _listCard));
    newCard->next = NULL;
    newCard->card = card;
    return newCard;
}

static void addCard(Deck deck, Card card) {
    assert(deck != NULL);
    ListCard newCard = newListCard(card);
    newCard->next = deck->top;
    deck->top = newCard;
}

我正在调用函数来执行上述操作,如下所示:

addToDeck(newgame->discard_pile, popCard(newgame->draw_pile));

但是,当我尝试使用以下命令释放甲板时,这会在gdb中引发无效的指针错误

freeDeck(newgame->discard_pile)

我是C内存管理的新手,我相信问题在于尝试释放不再指向内存分配起点的内存。

编辑:

游戏本身的初始化方式如下:

Game newGame(int deckSize, value values[], color colors[], suit suits[]) {
    // malloc a new game.
    Game newgame = malloc(sizeof(game));

    if (newgame == NULL) {
        fprintf(stderr, "Out of memory");
        return NULL;
    }
    // Otherwise there will be no cards to put into the draw pile.
    if (deckSize <= NUM_PLAYERS*DEFAULT_HAND) {
        return NULL;
    }

    newgame->deckSize = deckSize;

    // malloc the players in the game.

    Player players = malloc(NUM_PLAYERS*sizeof(struct _player));
    if (players == NULL) {
        fprintf(stderr, "Out of memory");
        return NULL;
    }

    // Instatiate each player object
    int i = 0;
    while (i < NUM_PLAYERS) {
        players[i].player_id = i;
        players[i].hand = newDeck();
        i++;
    }
    // Assign the players to the game.
    newgame->players = players;

    // Create decks of discard pile and draw_pile
    newgame->draw_pile = newDeck();
    newgame->discard_pile = newDeck();
    // loop through each of the values, colours and suits and create the necessary objects to star the game.

    i = 0;
    while (i < deckSize) {

        // Create a card from the array of values, colours and suits.
        Card card = newCard(values[i], colors[i], suits[i]);

        // Give each player 7 cards.
        if (i < DEFAULT_HAND*NUM_PLAYERS) {
            addToDeck(newgame->players[i % 4].hand, card);
        // After we have given each player seven cards fill the draw pile.
        } else {
            addToDeck(newgame->draw_pile, card);
        }

        i++;
    }

    // Push the first card onto the stack of the discard_pile.
    addToDeck(newgame->discard_pile, popCard(newgame->draw_pile));

    //Create the initial game state.

    GameState init = malloc(sizeof(struct _gamestate));
    init->curr_card = newgame->discard_pile->top->card;
    init->curr_player = 0;
    init->turn_number = 1;
    newgame->game_state = init;

    printGame(newgame);
    return newgame;
}

static Deck newDeck(void) {
    Deck deck = malloc(sizeof(struct _deck));

    if (deck == NULL) {
            fprintf(stderr, "Out of memory");
            return NULL;
    }

    deck->num_cards = 0;
    deck->top = NULL;
    return deck;
}

此功能可释放游戏:

void destroyGame(Game game) {
    GameState state = game->game_state;
    destroyCard(state->curr_card);
    free(state);
    Player players = game->players;
    int i = 0;
    while (i < NUM_PLAYERS) {
        freeDeck(players[i].hand);
        i++;
    }
    free(game->players);
    freeDeck(game->draw_pile);
    freeDeck(game->discard_pile);
    free(game);
}

free函数一直按预期运行,直到调用freeDeck(game-> discard_pile),通过该函数,我从draw_pile面板弹出的元素上的指针无效。进一步的测试表明,每次我从卡座上弹出卡时都会发生这种情况。

此刻的主要功能只是调用以下内容:

int main(void) {
    int decksize = 50;
    value values[decksize];
    color colors[decksize];
    suit suits[decksize];

    for (int i = 0; i < decksize; i++) {
            values[i] = rand() % 16;
            colors[i] = rand() % 16;
            suits[i] = rand() % 16;
    }
    Game cardgame = newGame(50, values, colors, suits);
    destroyGame(cardgame);
}

我的错误到底在哪里,我该如何解决?

0 个答案:

没有答案