Question

So, I'm trying to create a deck of cards using Linked List for a class, but I am having an extremely hard time trying to figure out why I have the error: Access violation reading location 0x00000020. I'm still new to coding and dynamic allocation, and I'm sure it's an easy fix, but I cannot for the life of me figure it out. My Deck class is the linked list, and my Card class is the node. The ultimate goal to make the game Crazy Eights. The Game class is supposed to hold four Decks (draw pile, discard pile, my hand, computer hand).

The code is breaking at SIZE++; in my addCard() function in deck.cpp

Deck.h

    #pragma once
    #include "Card.h"

    class Deck
    {
    protected:
        int SIZE;   //SIZE variable - indicates how many cards in deck
        Card *top;  //pointer to TOP of linked structure of cards

    public:
        //CONSTRUCTOR
        Deck();

        //FILL DECK
        void fill();                        //initialize the Deck to contain the standard 52 cards
        void addCard(int v, string s);      //*insert* a new card into the Deck

        //DRAW CARD
        Card *drawCard();                   //*remove* top card from the Deck and return it

        //FIND AND REMOVE
        void removeCard(int val, string s);//*find* a specific card and remove it from the Deck

        //SHUFFLE
        void shuffle();                     //randomize the order of cards in the Deck

        //PRINT
        void print();                       //displays the contents of the Deck
};

Deck.cpp

#include "Deck.h"
#include "Card.h"
#include <iostream>
using namespace std;

Deck::Deck()
{
    top = NULL;
    SIZE = 0;
}

void Deck::fill()
{
    string suit;
    for (int i = 0; i < 13; i++){
        for (int j = 0; j < 4; j++){
            switch (j){
                case 0: suit = "HEART"; break;
                case 1: suit = "DIAMOND"; break;
                case 2: suit = "CLUB"; break;
                case 3: suit = "SPADE"; break;
            }//end switch
            addCard(i, suit);
        }//end for
    }//end for
}//end fill

Card *Deck::drawCard()  
{
    Card *draw = top;
    top = top->getNext();
    SIZE--;
    return draw;
}//end drawCard

void Deck::removeCard(int val, string s)    
{
    //FINDS CARD
    Card *cur = top;
    while (cur != NULL && cur->getVALUE() != val && cur->getSUIT() != s)
        cur = cur->getNext();
    if (cur != NULL) 
        cout << cur->getVALUE() << cur->getSUIT();
    else{ 
        cout << "NOT FOUND";
        return;
    }//end else

    //REMOVES CARD
    Card *remove, *prev;
    if (top->getVALUE() == val && top->getSUIT() == s){
        remove = top;
        top = top->getNext();
        delete remove;
        SIZE--;
        removeCard(val, s);
    }//end if
    else{
        prev = top;
        while (prev->getNext() != NULL && prev->getNext()->getVALUE() != val && prev->getNext()->getSUIT() != s)
            prev = prev->getNext();
        if (prev->getNext() != NULL){
            remove = prev->getNext();
            prev->setNext(remove->getNext());
            delete remove;
            SIZE--;
            removeCard(val, s);
        }//end if
    }//end else
}//end removeCard

void Deck::addCard(int val, string s)
{
    SIZE++;
    top = new Card(val, s, top);
}//end addCard

//void Deck::shuffle()
//{
//    for (int i = 0; i < 7; i++)
//    {
//        // first break the deck into two half lists  -- like when you
//      //split the deck in half to shuffle
//        Deck half1;
//        Deck half2;
//        for (SIZE; SIZE > SIZE/2; SIZE--)
//        {
//            //draw card off the deck and add card to half1
//          SIZE--;
//        }//end for
//        for (int j = 0; j <= SIZE/2; SIZE++)
//        {
//            //draw card off the deck and add card to half2
//          SIZE++;
//        }//end for
//
//        // now repeatedly pull one card from either half1 or half2 and
//      // place it back on the deck -- like when the cards
//        // are falling back in random clumps during shuffling.
//        // we don't want to draw with 50-50 probability, instead we're
//      // going to skew the probability of selecting from
//        // each pile based on the relative size of the two piles.
//        while (/*half1 and half2 still have cards in them*/true)
//        {
//            int probPile1; //= size of half1 / (size of half1 + size of half2) * 100
//            int randomNum; //= random number between 1 and 100
//            if (randomNum <= probPile1)
//            {
//                //pull a card off half1 and add it back onto the deck
//            }//end if
//            else
//            {
//                //pull a card off half2 and add it back onto the deck
//            }//end else
//        }//end while
//  }//end for
//}//end shuffle

void Deck::print()
{
    cout << "Cards in pile: " << SIZE;
}//end print

Card.h

#pragma once
#include <string>
using namespace std;

class Card
{
    friend class Deck;  //allows Deck class access to Card's private member variables

    protected:
        int VALUE;      //value of card [1,2,3...11,12,13]
        string SUIT;    //HEART, DIAMOND, CLUB, SPADE
        Card *next;

    public:
        //CONSTRUCTORS/DESTRUCTOR
        Card();
        Card(int val, string s, Card *n);
        ~Card();
        Card *copy();

        //SETTERS: VALUE, SUIT, SYMBOL, next
        void setVALUE(int val)  {VALUE = val;}
        void setSUIT(string s)  {SUIT = s;}
        void setNext(Card *n)   {next = n;}

        //GETTERS: VALUE, SUIT, SYMBOL, next
        int getVALUE()          {return VALUE;}
        string getSUIT()        {return SUIT;}
        Card *getNext()         {return next;}

        void displayCard();
};

Card.cpp

#include "Card.h"
#include <iostream>
using namespace std;

Card::Card()
{
    VALUE = 0; SUIT = " "; next = NULL;
}

Card::Card(int val, string s, Card *n)
{
    VALUE = val; SUIT = s; next = n;
}

Card::~Card()
{
    if(next) free(next);
}

Card *Card::copy()
{
    Card *newCard = new Card(VALUE, SUIT, next);
    return newCard;
}

void Card::displayCard()
{
    cout << VALUE;
}

//tests whether two cards "match" -- comparison operator overload
bool operator == (Card &c1, Card &c2)
{
    return (c1.getVALUE() == c2.getVALUE() || c1.getSUIT() == c2.getSUIT());
}

Game.h

#pragma once
#include "Deck.h"

class Game
{
    protected:
        Deck *drawPile, *discardPile, *myHand, *compHand;
    public:
        Game();
};

Game.cpp

#include "Game.h"
#include "Deck.h"

Game::Game()
{
    drawPile = NULL; myHand = NULL; compHand = NULL; discardPile = NULL;

    drawPile->fill();
    for (int i = 0; i < 7; i++){
        myHand->drawCard();
        compHand->drawCard();
    }//end for
    discardPile->drawCard();
}

main.cpp

#include "Game.h"
#include <iostream>
using namespace std;

void main()
{
    Game crazyEights;

    system("PAUSE");
}
Was it helpful?

Solution

Here:

Game::Game()
{
  drawPile = NULL;

  drawPile->fill();
  ...
}

The pointer drawPile has value NULL, but you're telling the Deck it points to (which doesn't exist) to perform an operation. This is dereferencing a null pointer, and it causes undefined behavior.

Side note: it's important to be able to prepare a minimal complete example of a bug like this; it'll help you isolate the problem, so that you'll either find it yourself, or have a much simpler program for us to look at.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top