2016-12-03 15 views
0

私は地元の大学の学生である初心者のC++プログラマーです。私はこの課題を遂行しており、 "列車"を作るためにCarと呼ばれるクラスのリンクリストを作成するように言われています。私は単純に異なって印刷する2つの派生クラスを持っています。スコープの終わりにC++ダブルフリーまたは破損エラー

列車のリストを作成し、各タイプ(椅子と寝る)の現在の車を指し示す2つのポインタがあるので、ユーザーが特定のタイプの座席を予約したいときを知っています。列車、どこに行くのか正確に分かっています。列車がいっぱいになると、そのタイプの新しい列車を最後に配置する計画です。例:スリーピングカーの最後の座席が予約され、新しいスリーピングカーが作成され、列車の最後に置かれます。現在のスリープカーポインタは、リストの最後にある新しいカーをポイントします。

以下

このプログラムのために私が持っているコードです:

carTest.cc

int main() 
{ 
    int trainId = 0; 
    list<Car> train; 

    // Testing Car Default Constructor 

    // Testing Car Constructor 
    //cout << "Creating a \"Chair car\"... " << endl; 

    Car* currChair = nullptr, *currSleep = nullptr; 
    train.push_back(ChairCar(trainId++)); 
    currChair = &train.back(); 
    train.push_back(SleepingCar(trainId++)); 
    currSleep = &train.back(); 

    // Testing bookSeat 
    //book_seat_test(car2); 

    // Testing isTypeAvailable 
    //is_type_available_test(car2); 

    // Testing isBooked 
    //is_booked_test(car2); 

    // Testing mostAvailable 
    //most_available_test(car2); 

    // Testing firstAvailable 
    //first_available_test(car2); 

    // Testing getSeatNumber 
    ///get_seat_number_test(car2); 

    // Testing getIndex 
    //get_index_test(car2); 

    // Testing bookFirstAvailable 
    //book_first_available_test(car2); 

    // Testing chairCar printStatus 
    //chairCar_print_status_test(*currChair); 

    // Testing sleepingCar printStatus 
    //sleepingCar_print_status_test(*currSleep); 

    currSleep = nullptr; 
    currChair = nullptr; 
    return 0; 
} 

car.h

class Car 
{ 
public: 
    class Seat 
    { 
    public: 
    Seat() : row(-1), col(-1) {}; 
    Seat(int i, int j) : row(i), col(j) {}; 
    int getRow() const { return row; } 
    int getCol() const { return col; } 

    private: 
    int row; 
    int col; 
    }; 

public: 
    // Contructors 
    Car(); 
    explicit Car(int, int, int); 

    // Deconstructor 
    ~Car(); 

    // Public Member Functions 
    bool bookSeat(int, int); 
    bool isTypeAvailable(int) const; 
    bool isBooked() const; 
    int mostAvailable() const; 
    int firstAvailable(int) const; 
    int getSeatNumber(int, int) const; 
    Seat getIndex(int) const; 
    int bookFirstAvailable(int); 
    virtual void printStatus(int) const; 

protected: 
    int carNumber; 
    int rows; 
    int cols; 
    bool** plan; 
    int* numAvailable; 
    int columnSeperation; 

    void init(); 
}; 

car.cc

車スリーピング
// function: Deconstructor 
// Description: 
//    The Deconstructor simply frees the dynamically allocated memory 
// of the data members plan and numAvailable if the members are not pointing 
// to the nullptr. 
Car::~Car() 
{ 
    if(plan != nullptr) 
    { 
     delete[] plan; 
     plan = nullptr; 
    } 

    if(numAvailable != nullptr) 
    { 
     delete[] numAvailable; 
     numAvailable = nullptr; 
    } 
} 

chairCar.h

class ChairCar : public Car 
{ 
public: 
    ChairCar(); 
    ChairCar(int); 
protected: 
    void printStatus(int seatNumber) const; 
}; 

#endif 

chairCar.cc

#include "chairCar.h" 

ChairCar::ChairCar() 
    : Car() 
{ 

} 

ChairCar::ChairCar(int id) 
    : Car(7,4,id) 
{ 

} 

void ChairCar::printStatus(int seatNumber) const 
{ 
    int maxSeatNumber = (rows-1)*cols+(cols-1); 
    if(seatNumber > maxSeatNumber || seatNumber < 0) 
    throw OutOfRangeException(seatNumber, 0, maxSeatNumber); 

    cout << setw(columnSeperation) << ' ' << " |"; 
    cout << setw(columnSeperation) << "WL"; 
    cout << setw(columnSeperation) << "ML"; 
    cout << setw(columnSeperation) << "MR"; 
    cout << setw(columnSeperation) << "WR"; 
    cout << endl; 
    Car::printStatus(seatNumber); 
} 

異なる引数がベースのコンストラクタに送信されることを除い議長車とまったく同じです。私は、メイン関数内のコードを実行すると、私は取得

エラー `/ホーム/ w1llbedone /プログラミング/ cpsc2620/ASSN/A4/carTest '内:ダブル無料または破損(fasttop):0x0000000000608010

このエラーを回避するために、currCarポインタをnullptrに設定しようとしていましたが、スコープの終わりです。誰も私になぜこれが起こるか説明することができますか?これは初めてのStackExchangeでの投稿ですので、情報の不足についてお詫び申し上げます。どんな助けでも大歓迎です。

+0

SleepCarを 'list train;'にプッシュしないでください。私の推測では、それはコピーctorを介して車にスライスされている。 SleepCarの範囲はpush_backにあるため、そのリソースは解放されます。そして、メインの終わりに、リストのコピー(車)のdtorも解放されます。したがって、ダブルフリーです。 'リスト列車'またはそれ以上の 'list >'を使用してください。また、〜Car()は仮想でなければなりません。 –

+0

'Car'は自明ではないデストラクタを持っていますが、コピーコンストラクタやコピー代入演算子が表示されないので、動的に割り当てられたメンバを二重削除しています。 –

+4

[3つのルールとは何ですか?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)の可能な複製 –

答えて

1

部分的に表示されたコードには、少なくとも2つの大きなバグがあります。バグ#1:

これは教科書の場合、object slicingです。 trainは、std::listCarである。示されたコードはChairCarを構成し、それをリストに入れます。これによりサブクラスChairCarがスライスされ、Carスーパークラスがリストにコピーされます。

バグ2は、ここでの主要なバグです。このクラスviolates the Rule Of Threeです。 Carのデストラクタは明らかにdeleteです。ダイナミックスコープで構築されたクラスメンバです。ただし、Carクラスでは、コピーコンストラクタや代入演算子は定義されていません。これは、このクラスが3つのルールに従う可能性をかなり排除します。

したがって、これらの2つのバグは致命的な組み合わせになります。最初のオブジェクトのスライス中に、ChairCarオブジェクトは破棄されますが、そのCarスーパークラスのコピーがリストのコンテナにcopy-constructされた後でのみ破棄されます。破壊の一環として、Carのデストラクタdeleteは、その動的スコープのクラスメンバです。

はその後、最終的には、リストコンテナが破壊されますし、リストに、破壊されます、 Carをオフにスライスして、すでに delete Dだった deleteポインタへのデストラクタの試み。

ゲームオーバー。

関連する問題