C ++中带访问函数的分段错误

时间:2013-01-23 05:00:54

标签: c++ memory-management

我正在为C ++课做一个家庭作业,并遇到一些困难。我的程序是segfaulting由于“使用大小为8的未初始化值”和item :: name()中的“无效读取大小8”,由item :: operator =调用。

#ifndef ITEM_H
#define ITEM_H

const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;

class item {
public:
    // Constructors and deconstructor
    item();
    item(char* nme, double weight);
    virtual ~item();

    // Copy constructor
    item(const item& itm);

    // Overload assignment operator
    const item& operator=(const item& itm);

    // Overload inequality operator
    bool operator!=(const item&) const;

    // Mutators and accessors
    const char* name(void) const;
    double weight(void) const;
    void weight(double wght);
    void name(char* nme);

protected:
private:
    char* m_name;
    double m_weight;
};

#endif // ITEM_H

以下是我认为存在问题的实施部分:

... 

const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

const char* item::name(void) const {
    return m_name;
}

...

正如你所看到的,部分任务是使用c-strings,因此我陷入了凌乱的细节。我对指针和类的理解是,在使用它们时,我们需要实现析构函数,复制构造函数和重载赋值运算符。我已经完成了以上所有工作。我在Stack Overflow上查看了有关复制和交换习惯用法的一些信息,并尝试实现它,但无法使用我的代码。

我的大脑正在疲惫不堪,试图解开我出错的地方。有人可以告诉我我错过了什么吗?

谢谢!


修改

以下是构造函数,析构函数等:

item::item() {
    //ctor

    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
    this->weight(WEIGHT_DEFAULT);

    return;
}

item::item(char* nme, double wght) {
    m_name = new char[ITEM_NAME_LENGTH];

    strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);

    // We want to check for a rational value being
    // passed in to weight. In theory, an item has
    // to have *some* kind of weight, so we check
    // for a weight of 0. If a weight of 0 has been passed in,
    // we instead initialize the item's weight to the
    // default weight (set in the header file).
    if (wght > 0.0) {
        this->weight(wght);
    } else {
        this->weight(WEIGHT_DEFAULT);
    }

    return;
}

item::~item() {
    //dtor

    // TODO: We need to clean up any variables here.
    delete[] m_name;
}

item::item(const item& itm) {
    // copy ctor
    this->weight(itm.weight());
    strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);

}

const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

bool item::operator!=(const item& itm) const
{
    return (strcmp(m_name, itm.name()) != 0);
}

编辑2

现在我已经停止尝试动态分配名称c-string,我在重量函数上出现内存错误......

double item::weight(void) const {
    return m_weight;
}

void item::weight(double wght)
{
    m_weight = wght;
}

2 个答案:

答案 0 :(得分:1)

首先,您无需在return;语句中明确void

第二: 创建复制构造函数时,需要分配用于保存该构造函数内存的空间,与常规构造函数的操作方式相同。

在复制构造函数中尝试:

m_name = new char[ITEM_NAME_LENGTH];

编辑:为了完整性,我的“似乎正在工作”的代码是:

#include <stdio.h>
#include <string.h>


const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;

class item {
public:
    // Constructors and deconstructor
    item();
    item(char* nme, double weight);
    virtual ~item();

    // Copy constructor
    item(const item& itm);

    // Overload assignment operator
    const item& operator=(const item& itm);

    // Overload inequality operator
    bool operator!=(const item&) const;

    // Mutators and accessors
    const char* name(void) const;
    double weight(void) const;
    void weight(double wght);
    void name(char* nme);

protected:
private:
    char* m_name;
    double m_weight;
};


const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        m_name = new char[ITEM_NAME_LENGTH];
        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

const char* item::name(void) const {
    return m_name;
}

double item::weight(void) const {
    return m_weight;
}

void item::weight(double wght) {
    m_weight = wght;
}

item::item() {
    //ctor

    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
    this->weight(WEIGHT_DEFAULT);

    return;
}

item::item(char* nme, double wght) {
    m_name = new char[ITEM_NAME_LENGTH];

    strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);

    // We want to check for a rational value being
    // passed in to weight. In theory, an item has
    // to have *some* kind of weight, so we check
    // for a weight of 0. If a weight of 0 has been passed in,
    // we instead initialize the item's weight to the
    // default weight (set in the header file).
    if (wght > 0.0) {
        this->weight(wght);
    } else {
        this->weight(WEIGHT_DEFAULT);
    }

    return;
}

item::~item() {
    //dtor

    // TODO: We need to clean up any variables here.
    delete[] m_name;
}

item::item(const item& itm) {
    // copy ctor
    this->weight(itm.weight());
    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);

}

bool item::operator!=(const item& itm) const
{
    return (strcmp(m_name, itm.name()) != 0);
}


int main(int argc, char* argv[])
{
    item i("test",2.0);
    item b = i;
    item c;
    item d = c;
    return 0;
}

答案 1 :(得分:1)

我想使用std :: string作为练习的一部分,对吧?否则,这就是字符串处理的方法。您可以尝试的另一件事是避免动态分配字符串。相反,只需使用char m_name[ITEM_NAME_LENGTH];即可。顺便说一句:那是多长?如果它是名称中的最大字符数,则终止NUL需要+1

这就是说,还有一件事:在赋值运算符中,你比较if(this != &other),即你比较两个对象的地址。重点是避免自我分配,这很容易出错。您的作业检查名称是否不同,然后仅复制名称和重量。如果只有重量不同怎么办?