Reputation: 23
I'm new to C++. I do tried to find an answer on the books that I got and search on google but can not find a clue to the root of the problem.
It may be something really stupid. Hope someone could shed some light here I'm copying everything here below:
Hand::ShowHand2 is only working with "myHand.Add(pCard2)" somehow when I use myHand.Add(pCard1) I got the following error:
*** 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]
Here is the full code:
#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;
}
Big thanks in advance !
Upvotes: 1
Views: 3113
Reputation: 9547
You add pCard1
to your hand, which is a pointer to a local variable that will be destroyed automatically.
However, your ~Hand()
will call delete
on all cards it has assigned.
There you have your double free.
If you use pCard2
you allocated the Card
instance via new
and are therefore responsible for calling delete on it.
As you can see in the comments you should think about using smart pointers to avoid such problems.
Edit
To explain your main problem in more detail:
You use a pointer to a local variable which is automatically managed by the compiler.
However you then add()
it to the hand which takes ownership of the pointed object in that it will delete it, when the hand itself is destructed.
This basically leads to having two owners for the same object.
By generating an instance via new there is no owner who takes care of the destruction. However, when you add it to the hand then the hand owns it and will delete it.
Upvotes: 3
Reputation: 409146
Lets take this:
enum suit {club =1 , diamonds, hearts, spades};
Here you declare club
to be 1
, diamonds
to be 2
,`hearts
to be 3
and spades
to be 4
.
Then you have this array
const string SUITS[] = {"c", "d", "h", "s"};
that you index with the suit
.
However, arrays start their index with zero, which means that for a spade
you index out of bounds of the array, and enter the territory of undefined behavior when you use the "string" at SUITS[4]
.
Upvotes: 1