Search code examples
carraysdebuggingcorruption

My C array gets corrupted during execution


I'm writing a C program for a card game, and I'm currently making the algorithm to deal cards to each of the players. The problem is, for seemingly no reason, one of my array pointers is getting set to 0 during execution, and I can't figure out why. It seems to happen at a very specific spot in my code. Here is where I declare the array:

struct Hand *hands = (struct Hand*)calloc(players, sizeof(struct Hand));
for (int player = 0; player < leftovers; player++) {
    //Allocate an extra spot for these players, since they take an
    //extra card
    hands[player].cardv = (struct Card*)calloc((cardsperplayer + 1), sizeof(struct Card));
    hands[player].cardc = cardsperplayer + 1;
}
for (int player = leftovers; player < players; player++) {
    //Allocate the normal amount of cards for the rest of the players
    hands[player].cardv = (struct Card*)calloc((cardsperplayer), sizeof(struct Card));
    hands[player].cardc = cardsperplayer;
}

Next, we skip past the part where I make a deck of cards and fill it with cards values, to the point where I'm shuffling the cards in the deck, ready to deal them. It seems as soon as the shuffle finishes, the pointer to the hands array goes bad.

//Then we add the jokers on the end
struct Card blackJoker = {0, 13};
deck[52] = blackJoker;
struct Card redJoker = {1, 13};
deck[53] = redJoker;
//Now, we shuffle the deck using the Fisher Yates shuffle (the Durstenfeld version)
for (int cardsleft = 54; cardsleft > 0; cardsleft--) {
    swapCards(deck, cardsleft, rand() % cardsleft);
}
//IT SEEMS TO DROP THE HANDS ARRAY RIGHT HERE...run 
//Now that the cards are randomly shuffled, we just deal them out to
// everyone (it doesn't matter about the order, this is supposed to
//be truly random!
currentCard = 0;
for (int player = 0; player < leftovers; player++) {
    //Deal an extra card for these players, since they take an extra
    //card
    for (int card = 0; card < hands[player].cardc; card++) {
        hands[player].cardv[card] = deck[currentCard];
        currentCard++;
    }
}

The thing I don't get is, at no point directly before or after is the hands array accessed. But still, the hands array ends up dying and I get a Segfault for trying to access a crazy address. I'll include some of the other parts of the code too for reference.

void swapCards(struct Card *set, int a, int b) {
struct Card temp = set[a];
set[a] = set[b];
set[b] = temp;

Here's the structures I made to store the cards and hands:

struct Card {
int suit;
int value;
};

struct Hand {
    int cardc;
    struct Card* cardv;
};

If you want to run the full application, it's a C program hosted on Github, at https://github.com/Mikumiku747/kingandserf It shouldn't need any prerequisites apart from a C compiler and make. As for some final proof, I put it through the debugger, which is how I found the point where it all goes wrong:

Reading symbols from /home/pi/kingandtheserf/bin/kats...done.
(gdb) b cardops.c:90
Breakpoint 1 at 0x8a58: file src/cardops.c, line 90.
(gdb) b cardops.c:94
Breakpoint 2 at 0x8aa8: file src/cardops.c, line 94.
(gdb) b cardops.c:98
Note: breakpoint 2 also set at pc 0x8aa8.
Breakpoint 3 at 0x8aa8: file src/cardops.c, line 98.
(gdb) run a a a
Starting program: /home/pi/kingandtheserf/bin/kats a a a

Breakpoint 1, dealHands (players=4, sort=0) at src/cardops.c:91
91      for (int cardsleft = 54; cardsleft > 0; cardsleft--) {
(gdb) p hands
$1 = (struct Hand *) 0x13008
(gdb) p hands[0]
$2 = {cardc = 14, cardv = 0x13030}
(gdb) p hands[2]
$3 = {cardc = 13, cardv = 0x13120}
(gdb) c
Continuing.

Breakpoint 2, dealHands (players=4, sort=0) at src/cardops.c:98
98      currentCard = 0;
(gdb) p hands
$4 = (struct Hand *) 0x2
(gdb) p hands[0]
Cannot access memory at address 0x2
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x00008b30 in dealHands (players=4, sort=0) at src/cardops.c:102
102         for (int card = 0; card < hands[player].cardc; card++) {
(gdb) quit

Even if somebody doesn't know how to fix this, could they at least tell me what's going on. I've never seen this before, and my only guess right now is that the optimizer broke it somehow.


Solution

  • The first call to swapCards in the loop swaps the card at index 54 with another, but the highest index into the deck array is 53.