1

私はC++が初めてです。入手した本で答えを見つけようとしましたが、Google で検索しましたが、問題の根本的な手がかりを見つけることができません。

それは本当にばかげたことかもしれません。ここで誰かが光を当てることができることを願っています。以下にすべてをコピーしています。

Hand::ShowHand2 は、myHand.Add(pCard1) を使用すると、どういうわけか "myHand.Add(pCard2)" でのみ動作します。次のエラーが発生しました。

*** 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;
}

よろしくお願いします!

4

2 に答える 2

3

これは、自動的に破棄pCard1されるローカル変数へのポインターです。ただし、割り当てられたすべてのカード~Hand()を呼び出します。deleteそこにあなたのダブルフリーがあります。

使用する場合は、経由でインスタンスをpCard2割り当てたため、削除を呼び出す責任があります。Cardnew

コメントでわかるように、スマート ポインターを使用してこのような問題を回避することを検討する必要があります。

編集 主な問題をより詳細に説明するには: コンパイラによって自動的に管理されるローカル変数へのポインタを使用します。ただしadd()、手自体が破壊されたときに、それを削除するという点で、指し示したオブジェクトの所有権を取得する手になります。これは基本的に、同じオブジェクトに対して 2 人の所有者を持つことになります。

new を介してインスタンスを生成することにより、破壊を処理する所有者は存在しません。ただし、ハンドに追加すると、ハンドが所有し、削除されます。

于 2013-06-22T18:39:26.993 に答える
1

これを見てみましょう:

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

ここで、 である 、 である、である、であると宣言clubします。1diamonds2`hearts3spades4

次に、この配列があります

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

で索引付けすることsuit

ただし、配列はゼロでインデックスを開始します。これは、配列の範囲外にインデックスを付け、で「文字列」を使用すると未定義の動作spadeの領域に入ることを意味します。SUITS[4]

于 2013-06-22T18:39:47.067 に答える