2013-06-22 5 views
1

Я новичок в C++. Я пытался найти ответ на книги, которые у меня есть, и искать в google, но не могу найти ключ к корню проблемы.Двойная ошибка в C++

Это может быть что-то действительно глупое. Надежда кто-то может пролить некоторый свет здесь Я копирую все здесь ниже:

Hand :: ShowHand2 работает только с «myHand.Add (pCard2)» каким-то образом, когда я использую myHand.Add (pCard1) Я получил следующее сообщение об ошибке:

*** glibc detected *** /home/remy/workspace-C/myPoker/Debug/myPoker: double free or corruption (out): 0x00007fff7723d2d0 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fef4fd1bb96] 
/home/remy/workspace-C/myPoker/Debug/myPoker[0x401869] 
/home/remy/workspace-C/myPoker/Debug/myPoker[0x40172c] 
/home/remy/workspace-C/myPoker/Debug/myPoker[0x401b41] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fef4fcbe76d] 
/home/remy/workspace-C/myPoker/Debug/myPoker[0x400e19] 
======= Memory map: ======== 
00400000-00404000 r-xp 00000000 07:00 875533        /home/remy/workspace-C/myPoker/Debug/myPoker 
00603000-00604000 r--p 00003000 07:00 875533        /home/remy/workspace-C/myPoker/Debug/myPoker 
00604000-00605000 rw-p 00004000 07:00 875533        /home/remy/workspace-C/myPoker/Debug/myPoker 
02534000-02555000 rw-p 00000000 00:00 0         [heap] 

Вот полный код:

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 

class Card 
{ 
public: 
    enum rank {ace = 1, two, three, four, five, six , seven, eight, nine, ten, jack, queen, king}; 
    enum suit {club =1 , diamonds, hearts, spades}; 
    friend ostream& operator << (ostream& os, Card& aCard); 

    Card(rank r = ace, suit s = spades); 
    rank m_rank; 
    suit m_suit; 

}; 

Card::Card(rank r, suit s){ 
    m_rank = r; 
    m_suit = s; 
} 

ostream& operator<<(ostream& os, Card& aCard) 
{ 
    const string RANKS[] = {"0", "A", "2", "3", "4", "5", "6", "7", "8", "9", 
         "10", "J", "Q", "K"}; 
    const string SUITS[] = {"c", "d", "h", "s"}; 
    os << RANKS[aCard.m_rank] << SUITS[aCard.m_suit]; 

    return os; 
} 

class Hand 
{ 
    public: 
    Hand(); 
    virtual ~Hand(); 

void Add(Card* pCard); 
void Clear(); 
void ShowHand(); 
void ShowHand2(); 

    protected: 
    vector<Card*> m_Cards; 

}; 

Hand::Hand(){ 
    cout << "hand is created " << endl; 
    m_Cards.reserve(7); 
} 
Hand::~Hand() 
{ 
    Clear(); 
} 

void Hand::Add(Card* pCard) 
{ 
    cout << "*pCard: " << *pCard << " is @: " << pCard << endl; 
    m_Cards.push_back(pCard); 
} 

void Hand::Clear(){ 
    vector<Card*>::iterator iter = m_Cards.begin(); 
    for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter) 
    { 
    delete *iter; 
    *iter = 0; 
    } 
    m_Cards.clear(); 
} 


void Hand::ShowHand(){ 

     int k = 1; 
     vector<Card*>::iterator iter = m_Cards.begin(); 
    for (iter = m_Cards.begin() ; iter != m_Cards.end(); ++iter, ++k) 
    { 
     cout << "card no " << k << " is: "; 
     cout << **iter << endl ; 
    } 

} 


void Hand::ShowHand2(){ 

     vector<Card*>::iterator iter = m_Cards.begin(); 
     cout << "this hand has " << m_Cards.size() << " card(s)."<< endl; 

     for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter) 
{ 
    cout << **iter << endl; 
} 
} 



int main(){ 

Card c1(static_cast<Card::rank>(11), static_cast<Card::suit>(0)); 

Card* pCard1 = &c1; 
Card* pCard2; 
pCard2 = new Card(static_cast<Card::rank>(12), static_cast<Card::suit>(0)); 

Hand myHand; 

myHand.Add(pCard1); 
// myHand.Add(pCard2); 

// myHand.ShowHand(); 
myHand.ShowHand2(); 

cout << "End of Program" << endl; 


return 0; 
} 

Большое спасибо заранее!

+0

Вы пытались запустить программу с memcheck valgrind? – Nobody

+2

Прекратите использовать необработанные указатели и научитесь вводить код отступа, тогда мы можем поговорить. – Griwes

+2

Попробуйте использовать gdb для отладки кода. – arunmoezhi

ответ

3

Вы добавляете к вашей руке pCard1, что является указателем на локальную переменную, которая будет автоматически уничтожена. Тем не менее, ваш ~Hand() вызовет delete на всех назначенных картах. Там у вас есть ваш двойной бесплатный.

Если вы используете pCard2, вы назначили экземпляр Card через new и поэтому ответственны за его удаление.

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

Редактировать Чтобы объяснить свою главную проблему более подробно: используется указатель на локальную переменную, которая автоматически управляется компилятором. Однако вы тогда add() это к руке, которая берет на себя ответственность за заостренный объект тем, что он удалит его, когда сама ручка будет разрушена. Это в основном приводит к наличию двух владельцев для одного и того же объекта.

Создав экземпляр через новое, нет владельца, который позаботится об уничтожении. Однако, когда вы добавляете его в руку, тогда его владеет и удаляет.

+0

спасибо много @Nobody. на самом деле моя 400-страничная книга не упоминала даже «умный указатель». Я сейчас ищу googling ... надеюсь, что C++ не слишком умный, чтобы замедлить ppl, как я :( – Remyx

+0

Простите, что я не совсем понимаю ваш ответ. Когда вызывается '' Hand() 'это после' myHand.Add (pCard1); 'или' myHand.showHand2(); '? или после' return 0; ' – Remyx

+0

ok Я могу найти ответ, мне нужно добавить' delete pCard1; 'перед' return 0; '... – Remyx

1

Давайте так:

enum suit {club =1 , diamonds, hearts, spades}; 

Здесь вы объявляете club быть 1, diamonds быть 2, `hearts быть 3 и spades быть 4.

Тогда у вас есть этот массив

const string SUITS[] = {"c", "d", "h", "s"}; 

что индексирование с suit.

Однако массивы начинают свой индекс с нулевой , что означает, что для вас spade индекса за пределы массива, и въезд на территории непредсказуемого поведения при использовании «строки» в SUITS[4].

+0

спасибо @Joachim Pileborg. Теперь я изменил код на: const string SUITS [] = {"0", "c", "d", "h", "s"}; – Remyx