Что является причиной 'Неверный адрес, указанный для RtlValidateHeap (01480000, 014A2900) C -SDL-Blackjack.exe вызвал точку останова.' в этом проекте? - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь возиться с игрой в блэкджек на SDL, я понятия не имею, почему это происходит, но при попытке запуска появляется сообщение:

HEAP[C-SDL-Blackjack.exe]: Invalid address specified to RtlValidateHeap( 01480000, 014A2900 )
C-SDL-Blackjack.exe has triggered a breakpoint.

Похоже, что-то есть делать с:

Player::~Player()
{
    delete[] playerCartas;
}

Это находится в Player. cpp:

#include "Player.h"
/*!Player constructor receiving the deck as parameter to deal the cards
and dynamically allocating memory
*/
Player::Player(Deck& decko)
{
    playerCartas = new Card[2];
    playerCartas[0] = decko.dealCard();
    playerCartas[1] = decko.dealCard();
    card_num = 2;
    points = playerCartas[0].getPoint() + playerCartas[1].getPoint();
}

///Destructor of the class deleting the dynamic memory
Player::~Player()
{
    delete[] playerCartas;
}


///Function responsible to add a card to the player
void Player::SetCards(Deck& theDeck)
{
    card_num++;
    Card* tmp = new Card[card_num];
    int i = 0;
    for (i = 0; i < card_num - 1; i++) {
        tmp[i] = playerCartas[i];
    }
    tmp[i] = theDeck.dealCard();
    points += tmp[i].getPoint();
    playerCartas = tmp;
}

///Function that verifies if the player lost because it has more than 21 points
bool Player::bust()
{
    if (points > 21)
        return true;

    return false;
}

void Player::resetP(Deck & decko)
{

    ///Set new cards and update points and number of cards
    Card* tmp = new Card[2];
    playerCartas = tmp;
    playerCartas[0] = decko.dealCard();
    playerCartas[1] = decko.dealCard();

    card_num = 2;
    points = playerCartas[0].getPoint() + playerCartas[1].getPoint();
}

Также вот Player.h:

#pragma once
#include "Deck.h"

//!Player class that has a "hand" of maximum 5 cards and has actions with them
class Player {  
public:
    ///Players cards are not defined, so memory will be alocated dynamically
    ///Since player's cards are not a hidden, they are set to public 
    Card* playerCartas;/*!< the number of cards the player has*/

    int card_num; /*!< The number of cards the player has*/
    int points; /*!< The points of the player */

    //!Default constructor of the class
    Player(Deck& decko);

    //!Destructor of the class to delete the dynamic memory allocated
    ~Player();

    //!Function to set the cards to the player in ascending order
    void SetCards(Deck& theDeck);

    //!Function to return if player BUSTED
    bool bust();

    //!Reset the player after the round finishes
    void resetP(Deck& decko);
};

Колода. h:

#pragma once
#include "Card.h"
/*!This is the card's deck class, it must contain 52 cards with
four different suits: Clubs, diamonds, hearts and spades. This class
must have a function equivalent to a draw and a reset when one round is finished.*/
class Deck {
    Card allCards[52];/*!< Since the cards are a fixed number, no dynamic memory is needed*/

    int currentCard;/*!< Current card that will de dealt to the player or dealer*/
public:
    ///Constructor and initializator of the class that will
    ///create the deck and initialize the 52 cards
    Deck();

    //!Function that deals the first card based on the currentCard variable
    Card dealCard();
    //!Function to shuffle the cards inside the deck
    void shuffle();
};

Палуба. cpp

#include "Deck.h"

//!Player class that has a "hand" of maximum 5 cards and has actions with them
class Player {  
public:
    ///Players cards are not defined, so memory will be alocated dynamically
    ///Since player's cards are not a hidden, they are set to public 
    Card* playerCartas;/*!< the number of cards the player has*/

    int card_num; /*!< The number of cards the player has*/
    int points; /*!< The points of the player */

    //!Default constructor of the class
    Player(Deck& decko);

    //!Destructor of the class to delete the dynamic memory allocated
    ~Player();

    //!Function to set the cards to the player in ascending order
    void SetCards(Deck& theDeck);

    //!Function to return if player BUSTED
    bool bust();

    //!Reset the player after the round finishes
    void resetP(Deck& decko);
};

А вот и Источник. cpp:

#include <SDL.h>
#include <stdio.h>
#include "Deck.h"
#include "Card.h"
#include "Dealer.h"
#include "Player.h"
#include <string>
#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

///Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

const int nCards = 52;/*!< Since we do not need the joker, there will be only 52 cards in our Deck */

SDL_Window* janela = NULL; /*!< The window we'll be rendering to*/

SDL_Surface* superficie = NULL;/*!< The surface contained by the window*/

///Function responsible to initialize the SDL components
///The window that opens and the main surface of this window
bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        cout << "SDL could not initialize! SDL Error:"<< SDL_GetError() << endl;
        success = false;
    }
    else
    {
        //Create window
        janela = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if (janela == NULL)
        {
            cout<< "Window could not be created! SDL Error: "<< SDL_GetError()<< endl;
            success = false;
        }
        else
        {
            //Get window surface
            superficie = SDL_GetWindowSurface(janela);
        }
    }

    return success;
}

///Frees media and shuts down SDL
void close(SDL_Window* gWindow) {
    //Destroy window
    SDL_DestroyWindow(gWindow);
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

int main(int argc, char* args[]) {
    srand(time(0));/*!< Variable to generate random numbers*/

    SDL_Surface* ibagem_atual = NULL;/*!< Current displayed image*/

    SDL_Surface* ibagems[3]; /*!Initial MENU images*/
    ibagems[0] = SDL_LoadBMP("imgs/initial_page.bmp");
    ibagems[1] = SDL_LoadBMP("imgs/therules.bmp");
    ibagems[2] = SDL_LoadBMP("imgs/backgroundforplay.bmp");

    SDL_Surface* dealer_cards[2]; /*!< Surface containing the cards' images of the dealer*/

    SDL_Surface* backOfCard = NULL;/*!< Surface containing the card's BACK*/

    SDL_Rect dealerCardPlaceSecond = { 200,10,100,100 }; /*!< SDL Object that indicates the location of the image for the SECOND dealer card*/

    SDL_Surface* player_cards[5];/*!< Surface that contain the cards' images of the player*/

    SDL_Rect player_card_one_place = { 100,400,100,100 };/*!< SDL Object that indicates the location of the image*/

    /*----------------------------------------------------*/
    Deck mainDeck;/*!< Creates the fixed size deck and shuffle the cards*/

    ///Shufles the deck
    mainDeck.shuffle();

    Player playerOne(mainDeck);/*!< Creates the player*/

    Dealer dealerOne(mainDeck);/*!< Creates the dealer and deal 2 cards to it*/

    ///Start up SDL and create window
    if (!init())
    {
        cout << "Failed to initialize!\n"<< endl;
    }
    else {
        ///Main loop flag
        bool quit = false; /*!< Flag to show rules and never again after skipped*/

        bool rules = false;/*!< Flag to skip the reules screen after*/

        bool game_start = false;/*!< Flag to start game*/       

        bool pera = false;/*!< Flag to stop showing menu image*/

        bool reset = false;/*!< Flag to reset the game when lose or win*/

        bool bust = false;/*!< Flag to verify if player went BUST*/

        bool stand = false;/*!< Flag when player stand*/

        bool wait = false;/*!< Flag to wait response of player*/

        SDL_Event e;/*!< Event handler*/        

        ibagem_atual = ibagems[0];/*!< Setting the MENU to be displayed*/

        while (!quit) {

            while(SDL_PollEvent(&e) != 0) {
                ///In case of event Quit
                if (e.type == SDL_QUIT) {
                    quit = true;
                }
                ///In case of any keyboard event
                else if(e.type == SDL_KEYDOWN){
                    switch (e.key.keysym.sym)
                    {
                    ///Start the game and sets the rules and afterwards skip the rules
                    case SDLK_p:
                        if (rules == false) {
                            ibagem_atual = ibagems[1];
                            rules = true;
                        }                           
                        else {
                            ibagem_atual = ibagems[2];
                            game_start = true;
                        }                           
                        break;
                    ///Player asks for a card
                    case SDLK_DOWN:
                        if (bust != true && stand != true) {
                            playerOne.SetCards(mainDeck);
                            wait = false;
                        }                   
                        break;
                    ///Player stands
                    case SDLK_UP:
                        if (bust != true) {
                            stand = true;
                            wait = false;
                        }
                        break;
                    ///Restarts the game
                    case SDLK_LEFT:
                        pera = false;
                        game_start = false;
                        reset = true;
                        break;
                    default:
                        break;
                    }
                }
            }

            if(pera == false)
                SDL_BlitSurface(ibagem_atual, NULL, superficie, NULL);

            ///after reading the rules and pressing p, the cards will be dealt
            ///and the game starts
            if (game_start == true && wait == false) {

                pera = true;/*!< flag that clears the surcafe*/

                SDL_Rect dealerCardPlace = { 100,10,100,100 };/*!< SDL object with the coordinates to where the image should be placed*/

                ///Gets the path to the 2 cards of the dealer and load into SDL surfaces
                ///And also load the back of the card to another surface since one of them
                ///is hidden in the beginning of the game
                std::string path_dealer_Card_one = dealerOne.getCard(0);
                std::string path_dealer_Card_two = dealerOne.getCard(1);
                dealer_cards[0] = SDL_LoadBMP(path_dealer_Card_one.c_str());
                dealer_cards[1] = SDL_LoadBMP(path_dealer_Card_two.c_str());
                backOfCard = SDL_LoadBMP("imgs/backofthe_cards.bmp");

                SDL_BlitSurface(dealer_cards[0], NULL, superficie, &dealerCardPlace);

                ///If player chooses to stand, show the Dealer's hidden card
                ///In case the game is still on, show the back of the second card
                if (stand == false)
                    SDL_BlitSurface(backOfCard, NULL, superficie, &dealerCardPlaceSecond);
                else
                    SDL_BlitSurface(dealer_cards[1], NULL, superficie, &dealerCardPlaceSecond);             

                ///Logic to show the player's cards
                for (int cnt = 0; cnt < playerOne.card_num; cnt++) {
                    std::string player_path = playerOne.playerCartas[cnt].toString();
                    player_cards[cnt] = SDL_LoadBMP(player_path.c_str());

                    SDL_Rect player_card_two_place = { 100+cnt*90,350,100,100 };

                    SDL_BlitSurface(player_cards[cnt], NULL, superficie, &player_card_two_place);
                }

                wait = true;/*!< flag to wait the action of the player*/

                ///Logic if the next card drwan makes the player lose
                bust = playerOne.bust();
                if (bust == true) {
                    SDL_Rect busted_rect = { SCREEN_WIDTH / 2-150,SCREEN_HEIGHT / 2-84,300,300 };
                    SDL_Surface* busted = SDL_LoadBMP("imgs/busted.bmp");

                    SDL_BlitSurface(busted, NULL, superficie, &busted_rect);
                }

                ///Logic to solve if player standed and give result if win or lose
                if (stand == true) {
                    if (dealerOne.getPoints()> playerOne.points) {
                        SDL_Rect lose_rect = { SCREEN_WIDTH / 2 - 150,SCREEN_HEIGHT / 2 - 84,300,300 };
                        SDL_Surface* lose = SDL_LoadBMP("imgs/lose.bmp");
                        SDL_BlitSurface(lose, NULL, superficie, &lose_rect);

                    }
                    else {
                        SDL_Rect win_rect = { SCREEN_WIDTH / 2 - 150,SCREEN_HEIGHT / 2 - 84,300,300 };
                        SDL_Surface* win = SDL_LoadBMP("imgs/win.bmp");
                        SDL_BlitSurface(win, NULL, superficie, &win_rect);
                    }
                }

            }   

            if (reset == true) {

                SDL_BlitSurface(ibagems[2], NULL, superficie, NULL);/*!< flag to clean the surface back to false*/

                ///Reset the flags that end the game
                bust = false;
                stand = false;

                ///Set new cards to the dealer and update points
                dealerOne.reset(mainDeck);

                ///Updates points, set new cards and delete the other cards
                playerOne.resetP(mainDeck);

                ///Update the flags
                game_start = true;
                wait = false;
                reset = false;

            }

            ///Function to update the Window
            SDL_UpdateWindowSurface(janela);
        }
    }
    ///calling the destructor of the class to delete the dynamically allocated memory
    playerOne.~Player();

    close(janela);

    return 0;
}

1 Ответ

1 голос
/ 26 апреля 2020

Вы вызываете деструктор объекта с автоматическим c сроком хранения вручную

playerOne.~Player();

Никогда не делайте этого . Деструктор будет вызываться автоматически, когда playerOne выходит из области видимости. Таким образом, в этом случае деструктор будет вызываться дважды (один раз вручную, один раз, когда player1 выйдет из области видимости).

Первый раз это работает, но во второй раз он пытается delete[] память, которая уже была освобождена / удалена при первом вызове. Это вызывает ошибку.

Просто удалите эту строку, она вам не нужна.

...