2015-04-05 139 views
1

基本上我的代码崩溃,我不能找出原因,我已经使用的代码:: Blocks的调试器,但对我来说没有任何帮助。它会在打印出属性的正确数据后崩溃[4]。我知道这不是实现这一目标的最佳方式,但是对于需要展示可以完成的多种方式的课程而言,我的问题是它显示“河桂餐厅”后崩溃,无法找出原因。COUT打印后崩溃对象的getter

const int MAX_PROPERTIES = 5; 

int main(void) { 
    Property properties[MAX_PROPERTIES]; 
    Rentals tempRent; 

    tempRent = Rentals(); 
    tempRent.setBond(10000); 
    tempRent.setMonthlyRent(700); 

    tempRent.setOwner("River Kwai Restaurant"); 
    tempRent.setAddress("3 Bishopton Road"); 
    tempRent.setSuburb("Footscray"); 
    tempRent.setPostcode(5000); 

    properties[4] = tempRent; 
    tempRent.~Rentals(); 

    cout << properties[4].getOwner() << endl; 


    return 0; 
} 

Property::Property(){ 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
} 

Property::Property(string theOwner, string theAddress, 
        string theSuburb, int thepostCode): 
        owner(theOwner), address(theAddress), 
        suburb(theSuburb), postcode(thepostCode){} 

Property::~Property() {} 

Rentals::Rentals(string theOwner, string theAddress, string theSuburb, 
        int thePostCode, double theBond, double theMonthlyRent): 
        Property(theOwner, theAddress, theSuburb, thePostCode), 
        bond(theBond), monthlyRent(theMonthlyRent){} 

Rentals::Rentals() : Property() { 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
    bond = 0; 
    monthlyRent = 0; 
} 

Rentals::~Rentals() {} 

注:删除析构函数确实解决了它,但我想知道为什么?应该析构函数不会影响属性[4],因为它已经被初始化了?

也就是说相关的代码,但我会后,如果需要下面的整个代码/头文件。

#include "property_a.h" 
#include "rentals.h" 
#include "commercial.h" 
#include "sales.h" 

const int MAX_PROPERTIES = 5; 

int main(void) { 
    Property properties[MAX_PROPERTIES]; 
    Rentals tempRent; 

    properties[0] = Commercial("Notting Hill McDonalds", 
           "4 Gardiner Road", "Notting Hill", 5000, 
           "Li3000"); 

    properties[1] = Rentals("Janet Dalgleish", "30 Firhill Court", 
          "Mary Hill", 4000, 500.00, 300.00); 

    properties[2] = Sales("Robert Burns", "3 Ayr Court", "Irvine", 4000, 
         "10/10/2015", 700000); 

    properties[3] = Property(); 
    properties[3] = properties[0]; 


    tempRent = Rentals(); 
    tempRent.setBond(10000); 
    tempRent.setMonthlyRent(700); 

    tempRent.setOwner("River Kwai Restaurant"); 
    tempRent.setAddress("3 Bishopton Road"); 
    tempRent.setSuburb("Footscray"); 
    tempRent.setPostcode(5000); 

    properties[4] = tempRent; 

    cout << properties[4].getOwner() << endl; 


    return 0; 
} 

Property::Property(){ 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
} 

Property::Property(string theOwner, string theAddress, 
        string theSuburb, int thepostCode): 
        owner(theOwner), address(theAddress), 
        suburb(theSuburb), postcode(thepostCode){} 

Property::~Property() {} 

Commercial::Commercial() : Property() { 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
    license = "NULL"; 
} 

Commercial::Commercial(string theOwner, string theAddress, 
         string theSuburb, int thepostCode, 
         string theLicense): Property(theOwner, theAddress, 
         theSuburb, thepostCode), license(theLicense) {} 

Commercial::~Commercial() {} 

Rentals::Rentals(string theOwner, string theAddress, string theSuburb, 
        int thePostCode, double theBond, double theMonthlyRent): 
        Property(theOwner, theAddress, theSuburb, thePostCode), 
        bond(theBond), monthlyRent(theMonthlyRent){} 

Rentals::Rentals() : Property() { 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
    bond = 0; 
    monthlyRent = 0; 
} 

Rentals::~Rentals() {} 

Sales::Sales(string theOwner, string theAddress, string theSuburb, 
       int thepostCode, string theAuctionDate, double thePrice): 
       Property(theOwner, theAddress, theSuburb, thepostCode), 
       auctionDate(theAuctionDate), price(thePrice) {} 

Sales::Sales() : Property() { 
    owner = "NULL"; 
    address = "NULL"; 
    suburb = "NULL"; 
    postcode = 0; 
    auctionDate = "NULL"; 
    price = 0; 
} 

Sales::~Sales() {} 

物业头

#ifndef __PROPERTY_A_H__ 
#define __PROPERTY_A_H__ 


/*TODO REQUIRED HEADER FILES AND NAMESPACES*/ 
#include <string> 
#include "utility1.h" 


class Property 
{ 
protected: 
    string owner; 
    string address; 
    string suburb; 
    int postcode; 

public: 
    Property(); 
    Property(string theOwner, string theAddress, string theSuburb, int thepostCode); 
    virtual ~Property(); 

    string getOwner() const {return owner;}; //Note the use of const 
    string getAddress() const {return address;}; 
    string getSuburb() const {return suburb;}; 
    int getPostcode() const {return postcode;}; 

    void setOwner(string newOwner) {owner = newOwner;}; 
    void setAddress(string newAddress) {address = newAddress;}; 
    void setSuburb(string newSuburb) {suburb = newSuburb;}; 
    void setPostcode(int newPostcode) {postcode = newPostcode;}; 
}; 
#endif 

出租头

#ifndef __RENTALS_H__ 
#define __RENTALS_H__ 


#include "property_a.h" 

class Rentals : public Property 
{ 
protected: 
    double bond; 
    double monthlyRent; 

public: 
    Rentals(); 
    Rentals(string theOwner, string theAddress, string theSuburb, 
       int thepostCode, double theBond, double theMonthlyRent); 
    ~Rentals() ; 

    double getBond() const {return bond;}; //Note the use of const 

    void setBond(double theBond) {bond = theBond;}; 

    double getMonthlyRent() const {return monthlyRent;}; //Note the use of const 

    void setMonthlyRent(double theMonthlyRent) {monthlyRent = theMonthlyRent;}; 


}; 

#endif 
+1

你应该谷歌'对象slice' – billz 2015-04-05 10:07:09

回答

1

另一位评论者建议您查找object slicing.这并不说明问题,但是你可以通过添加一些调试语句,更具体地看到它您的代码:

std::cout << "Size of properties: " << sizeof(properties) << std::endl; 
std::cout << "Size of properties[4]: " << sizeof(properties[4]) <<std::endl; 
std::cout << "Size of tmpRent: "<< sizeof(tempRent) <<std::endl; 

输出看起来是这样的:

Size of properties: 440 
Size of properties[4]: 88 
Size of tmpRent: 104 

它看起来像一个属性元素是不是大到足以容纳你的子类的元素......这是怎么回事?

在声明Properties properties[5],你正在声明类型属性的对象的数组,并将其分配的存储器的连续块。实际上,你可以看到,通过打印地址:

std::cout << "Start of properties: " << &properties <<std::endl; 
std::cout << "Address of properties[0]: " << &properties[0] << std::endl; 
std::cout << "Address of properties[1]: " << &properties[1] << std::endl; 
std::cout << "Address of properties[2]: " << &properties[2] << std::endl; 
std::cout << "Address of properties[3]: " << &properties[3] << std::endl; 
std::cout << "Address of properties[4]: " << &properties[4] << std::endl; 

在我的机器,我得到:

Start of properties: 0x7fff5a4c6070 
Address of properties[0]: 0x7fff5a4c6070 
Address of properties[1]: 0x7fff5a4c60c8 
Address of properties[2]: 0x7fff5a4c6120 
Address of properties[3]: 0x7fff5a4c6178 
Address of properties[4]: 0x7fff5a4c61d0 

这些都是很大的数字,但你可以看到,地址是由将0x58或88字节增加为数组中的每个元素。当你分配属性[4]时,C++将属性[4]作为指针处理,并将104字节复制到指向的位置。赋值属性[4] = tempRent相当于memcpy(&tempRent, &properties[4], 104)。 C++只是假设你有足够的内存来存放对象(这是104字节)。但是在内存块结束之前只剩下88个字节。您的分配将覆盖阵列的末尾并破坏下一段内存。该程序可能会崩溃在任何时候,它可能会显示损坏的数据,或者它可能看起来完全正常工作(因为它,当我在我的Mac上运行它。)

+0

这非常有意义谢谢,但我真的不明白,它只会调用属性[4]函数时崩溃,因为它应该损坏下一个内存而不是当前内存。它只是不幸的是它正在腐蚀和崩溃的地方?或者是否在88字节信息末尾丢失了类末尾的内容? – 2015-04-07 02:28:16

+0

也意思,这样做创建指针数组的适当方法将解决此问题作为使用声明属性时的新的关键字[4] =新线路()将分配线路()大小存储器(这种情况下104个字节),以属性[4]不是88字节? – 2015-04-07 02:47:46

+0

@RoryThoman你说得对'幸运'部分是正确的。你真的不知道它会在哪里崩溃。如果内存块位于有效分配内存的边缘,那么当您写入属性[4]时,您的进程可能会崩溃,但它最有可能是您的程序已“拥有”了相邻的空间,因此操作系统不会帮助你解决分段错误。 创建一个指针数组可以让你分配任何类型的属性,但你必须先为它分配内存。租金* tempRental =新租金()。另外,你必须记得删除内存。 – ericzundel 2015-04-07 12:24:38