2016-12-03 22 views
0

我是新手C++程序員,他目前是我本地大學的一名學生。我正在做這個任務,並且我被告知創建一個名爲Car的類的鏈表來創建一個「火車」。我有兩個派生類,只是打印不同。C++ double免費或在範圍結束時出現錯誤錯誤

我想要做的是創建列車車廂列表,並且有兩個指向每種類型(椅子和睡覺)的當前車的指針,以便我知道用戶何時想要預訂某種類型的座位火車,我知道到哪裏去。當一列火車滿了時,計劃就是把這種新的列車結束。例如:睡車的最後一個座位被預訂,一輛新的睡車將被創建並放在火車的盡頭。現在的睡車指針現在將指向列表末尾的新車。

下面是我對這個程序的代碼:

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推入「列表列車」。我猜想它已經通過copy ctor切片成Car了。 SleepCar的範圍在push_back中,因此其資源被釋放。在main的結尾,列表中副本(Car)的dtor也被釋放,因此double free。使用列表列車'或更好'列表>'。另外〜Car()應該是虛擬的。 –

+0

'Car'有一個非平凡的析構函數,但是我沒有看到任何拷貝構造函數或拷貝賦值操作符,所以你會雙重刪除你的動態分配的成員。 –

+4

[三條法則是什麼?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-ree) –

回答

1

部分顯示的代碼至少有兩個主要的錯誤。錯誤#1:

list<Car> train; 

// ... 

train.push_back(ChairCar(trainId++)); 

這是object slicing一個教科書案例。 trainCar s的std::list。顯示的代碼構造一個ChairCar,並將其放入列表中。這將切掉ChairCar子類,並將Car超類複製到列表中。

Bug#2是這裏的主要bug:這個類violates the Rule Of Three。明確的delete的動態範圍構造的類成員。但是,Car類沒有定義複製構造函數,也沒有定義賦值運算符。這幾乎排除了該課程符合三級規則的可能性。

因此,這兩個錯誤會導致致命的組合。在初始對象切片期間,暫時的ChairCar對象被破壞,但是隻有在其超類的副本被拷貝構建到列表的容器中之後纔會被銷燬。作爲銷燬的一部分,Car的析構函數delete是其動態範圍的類成員。

然後,最終,列表容器被銷燬,列表中被切掉的Car被破壞,並且其析構函數嘗試到delete指針,該指針已經是delete d。

遊戲結束。