简体   繁体   中英

Segmentation Fault (C++)

My code so far is intended to create a deck of cards, values 9 - ACE of each suite, and deal 5 cards to 4 players. The cards are deal 3-2-3-2 and then 2-3-2-3 so each player has 5 total cards. Later on I will write code to shuffle the cards and then compare them in a game of euchre, but for now I just want to deal the cards. Anyway it doesn't exactly work and I'am open for suggestion. The Error I get is "Segmentation fault: 11"

#include <iostream>
#include <fstream>
#include <cstring>
#include <string>

using namespace std;

int cards[24]; //array filled with card values
char DECK[24][25] = 
{ //array filled with card names. Used for dealing //24elements long //25 characters in    each element
"Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",

"Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",

"Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",

"Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};

int main (void)
{
char P1[5][25];
char P2[5][25];
char P3[5][25];
char P4[5][25];

for( int i = 0 ; i < 24 ; ++i) // for the total amount of cards
{
  for(int j = 0; j < 25; j++)
  {
      //1st deal 3-2-3-2
      if(i < 3) // 0 - 2 // 3 cards
      {
        P1[i][j] = DECK[i][j];
      }
  if((i > 2) && (i < 5))// 3 - 4 // 2 cards
  {
    P2[i][j] = DECK[i][j];
  }
  if((i > 4) && (i < 8)) // 5 - 7 // 3 cards
  {
    P3[i][j] = DECK[i][j];
  }
  if((i > 7) && (i < 10))// 8 - 9 // 2 cards
  {
    P4[i][j] = DECK[i][j];
  }
  //2nd deal 2-3-2-3
  if((i > 9) && (i < 12)) // 10 - 11 // 2 cards
  {
    P1[i][j] = DECK[i][j];
  }
  if((i > 11) && (i < 15))// 12 - 14 // 3 cards
  {
    P2[i][j] = DECK[i][j];
  }
  if((i > 14) && (i < 17)) // 15 - 16 // 2 cards
  {
    P3[i][j] = DECK[i][j];
  }
  if((i > 16) && (i < 20))// 17 - 19 // 3 cards
  {
    P4[i][j] = DECK[i][j];
  }
  }
}

for(int q = 0; q < 5; ++q)
{
  cout << "P1 has the card " << P1[q]<< endl;
}
for(int q = 0; q < 5; ++q)
{
  cout << "P2 has the card " << P2[q]<< endl;
}
//for(int q = 0; q < 5; ++q)
{
  //cout << "P3 has the card " << P3[q]<< endl;
}
//for(int q = 0; q < 5; ++q)
{
 //cout << "P4 has the card " << P4[q]<< endl;
}

return 0;
}

Let me "teach you to fish":

A debugger will tell you exactly where the fault is. If you're using an IDE (Xcode, Eclipse, VS) it has a nice interface to one and you should use that. If not:

$ gdb my_executable
...
> run
...
Segmentation fault
> where

This will give you the exact location (which function on which line number).

You have arrays like this

char P1[5][25];

and yet in your code you are assigning values to elements where the i index is larger than 5. You must limit your indices to assign to elements that are valid and in range. It is only valid to assign to values of P1[i][j] for i between 0 and 4 and j between 0 and 24. If you deviate from this you run risk of segmentation fault as you should not be assigning to memory locations that are outside the array bounds.

 if((i > 4) && (i < 8)) // 5 - 7 // 3 cards
  {
    P3[i][j] = DECK[i][j];

you are assigning to P3[5]... P3[6]... P3[7]...which don't exist. Later you are doing the same with even bigger indexes. You must use i=[0,4] j=[0,24]

Allow me to also "teach you to fish" on a slightly different angle.

Your code uses two constant numbers, 24 and 25. I had a hard time reading your code because you appear to use 25 twice for different purposes.

Instead of using raw constant numbers, give them meaningful names. This will help you to document your code but will also help you to avoid silly mistakes. There are three ways you can do this.

C style:

#define NUM_CARDS_IN_DECK 24

Pros: Wherever you write 'NUM_CARDS_IN_DECK' after this, the compiler will see the constant "24" and do appropriate type conversion. Cons: You can't tell where the value came from in a debugger.

Enum:

enum { NumCardsInDeck = 24 };

Pros: Appears in some debuggers, Cons: Sometimes you may have to cast.

Enum:

static const size_t NumCardsInDeck = 24;

Pros: Strongly typed, generally appears in debuggers, Strongly typed, Cons: Strongly typed.

But lets look at how this changes your code:

static const size_t NumCardsInDeck = 24;
static const size_t MaxCardNameLength = 25;

int cards[NumCardsInDeck];
char DECK[NumCardsInDeck][MaxCardNameLength] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};

int main()
{
    char P1[5][MaxCardNameLength];
    char P2[5][MaxCardNameLength];
    char P3[5][MaxCardNameLength];
    char P4[5][MaxCardNameLength];

    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        for(int j = 0; j < 25; j++)

Here we come across what is likely to be the bug. You've used the number 25 here and I suspect you didn't mean to.

        for(size_t j = 0; j < MaxCardNameLength; j++)

Is that what you intended to write? You're going to copy each individual character based on the value of the outer loop, i? The code doesn't look like it will work because your code says

0 <= i < NumCardsInDeck where NumCardsInDeck goes to 25

but your definition of P1 says

0 <= index P1 < 5

5 is clearly smaller than 25, so you are going to overflow the first index of P1, same for P2 etc.

At a guess, "P" is for player and 5 is the size of a hand. It looks like you are actually copying the entire card name from the deck into the hand. You can simplify this by using a "const char*" to point to the names:

static const size_t NumCardsInDeck = 24;
static const size_t NumCardsPerHand = 5;

int cards[NumCardsInDeck];
const char* DECK[NumCardsInDeck] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};

int main()
{
    const char* P1[NumCardsPerHand];
    const char* P2[NumCardsPerHand];
    const char* P3[NumCardsPerHand];
    const char* P4[NumCardsPerHand];

    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        if(i < 3)
        {
            P1[0] = DECK[i];
        }
        else if(i < 6)  // it's an else, so i > 2 is already implied.
        {
            P1[1] = DECK[i];
        }
        ...

Ok - we're making progress here, but you're still going to run into a problem, let's simplify this by using some more constant names and make the players into a single entity. And trim this into a single, runnable stage.

#include <iostream>

static const size_t NumCardsInDeck = 24;
static const size_t NumCardsPerHand = 5;
static const size_t NumPlayers = 4;

// removed 'cards' because we aren't using it.
const char* DECK[NumCardsInDeck] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};

int main()
{
    const char* hands[NumPlayers][NumCardsPerHand];
    enum { Player1, Player2, Player3, Player4 }; // For indexing the hands.

    std::cout << "We have " << NumPlayers << " hands of " << NumCardsPerHand << " cards." << std::endl;
    std::cout << "Total cards that will be dealt: " << NumPlayers * NumCardsPerHand << std::endl;

    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        if(i < 3)
        {
            hands[Player1][0] = DECK[i];
        }
        else if(i < 6)  // it's an else, so i > 2 is already implied.
        {
            hands[Player2][0] = DECK[i];
        }
        else
        {
            break;
        }
    }

    std::cout << "hands[0][0] = " << hands[0][0] << std::endl;
    std::cout << "hands[1][0] = " << hands[1][0] << std::endl;

    return 0;
}

You can see this code running here: http://ideone.com/8MUOCt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM