Проблема повреждения кода между вызовом функции и первой строкой функции в visual studio - PullRequest
1 голос
/ 04 марта 2020

Я использую Visual Studio для компиляции и запуска карточной игры. Кажется, у меня проблема, когда я вызываю функцию get_top_card ()

void Deck::shuffle(){
    //This function shuffles the deck.
    Deck tempdeck;                                      
    while (cards.size() > 0)                            
    {
        int cardnumber = -1;                            
        cardnumber = rand() % cards.size();             
        tempdeck.add_card_to_deck(cards[cardnumber],false); 
        erase_card(cardnumber);                         
    }
    while (tempdeck.size() >0){                         
        add_card_to_deck(tempdeck.get_top_card(),false);   //error occurs in this function
    }
}


void Deck::add_card_to_deck(Card& card1, bool shift){       //Lets call this line A
    if (face_up) card1.set_face_up();                       //Lets call this line B
    else card1.set_face_down();
    Point new_location(decklocation.x , decklocation.y + cards.size() * 25);
    if (shift) card1.move_card(card1.location(), new_location);
    else card1.move_card(card1.location(), decklocation);
    card1.button()->hide();
    cards.push_back(card1);
}

Когда я запускаю этот код с использованием отладчика, я вижу в переменных времени, что в строке A card1 есть действительное значение карты .. . просмотр переменной

Когда я попадаю в строку B, карта1 теперь повреждена .. просмотр поврежденной переменной

Есть идеи?

Card& Deck::get_top_card()          //returns the top card and removes it from the deck
{
    Card top_card = cards[cards.size()-1];      //holds the card
    erase_card(cards.size()-1);                 //deletes it from the deck
    return top_card;                
}

Я думаю, что нашел проблему, см. Ниже ... тестирование сейчас

Card& Deck::get_top_card()          //returns the top card and removes it from the deck
{
    Card& top_card = cards[cards.size()-1];     //holds the card
    erase_card(cards.size()-1);                 //deletes it from the deck
    return top_card;                
}

Это была проблема ... Я возвращал карту, а не указатель. Спасибо всем за помощь!

Обновление: я изменил код еще больше из-за проблем, которые здесь не удалось

  1. Я изменил вектор своих личных карточек на вектор карточных указателей, и я помещаю их в вектор, используя new.
cards.push_back (new Card(suit,name,value,symbol,file));
Это означает, что мои функции теперь являются типами указателей:
Card* Deck::get_top_card()          //returns the top card and removes it from the deck
{
    Card* top_card = cards[cards.size()-1];     //holds the card
    cards.erase(cards.end()-1);                 //deletes it from the deck
    return top_card;                
}

void Deck::add_card_to_deck(Card* card, bool shift){        //adds a card to the bottom of the deck.
    if (face_up) card->set_face_up();
    else card->set_face_down();
    Point new_location(decklocation.x , decklocation.y + cards.size() * 25);
    if (shift) card->move_card(card->location(), new_location);
    else card->move_card(card->location(), decklocation);
    card->button()->hide();
    cards.push_back(card);
}

Это, похоже, решило проблемы, с которыми я столкнулся. Он также позволяет хранить только одну копию каждой карты, поскольку адрес - это то, что хранится и передается.

Кто-нибудь видит что-то еще, что мне может понадобиться знать?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Первая версия:

Card& Deck::get_top_card()          //returns the top card and removes it from the deck
{
    Card top_card = cards[cards.size()-1];      //holds the card
    erase_card(cards.size()-1);                 //deletes it from the deck
    return top_card;                
}

недопустима, поскольку вы возвращаете ссылку на объект top_card, область действия которого заканчивается. Этот хранится в стеке и может быть легко переопределен. Кроме того, ЦП может проверить доступ к памяти выше кончика стека, что приводит к взлому sh.

Эта версия также недопустима:

Card& Deck::get_top_card()          
{
    Card& top_card = cards[cards.size()-1];     //needed to create a reference.
    erase_card(cards.size()-1);                 
    return top_card;                
}

, так как в этот раз вы возвращаете ссылку на кончик вектор, который расположен на куче, и вы уменьшаете размер вектора. Это неопределенное поведение.

Это работает, поскольку в этом сценарии векторный буфер не перераспределяется, просто размер вектора уменьшается на единицу. В результате ссылка указывает на допустимый кусок памяти (это предотвращает cra sh), но это все еще ошибка переполнения буфера.

Скорее всего, правильный способ исправить это допинговая ссылка из возвращаемого типа:

Card Deck::get_top_card()deck
{
    Card top_card = cards[cards.size()-1];
    erase_card(cards.size()-1);
    return top_card;                
}

Я сомневаюсь, что ваш Card является сложным типом и, скорее всего, может быть дешево скопирован.

0 голосов
/ 04 марта 2020

Проблема была в моей функции получить верхнюю карту.

Card& Deck::get_top_card()          
{
    Card& top_card = cards[cards.size()-1];     //needed to create a reference.
    erase_card(cards.size()-1);                 
    return top_card;                
}

Обновление: кажется, это лучший ответ:

void Deck::add_card_to_deck(Card* card, bool shift){        //adds a card to the bottom of the deck.
    if (face_up) card->set_face_up();
    else card->set_face_down();
    Point new_location(decklocation.x , decklocation.y + cards.size() * 25);
    if (shift) card->move_card(card->location(), new_location);
    else card->move_card(card->location(), decklocation);
    card->button()->hide();
    cards.push_back(card);
}

Card* Deck::get_top_card()          //returns the top card and removes it from the deck
{
    Card* top_card = cards[cards.size()-1];     //holds the card
    cards.erase(cards.end()-1);                 //deletes it from the deck
    return top_card;                
}

...