c++ - 导致段错误的析构函数

标签 c++

我已经实现了一个类似于 std::string 的类字符串。 调用析构函数时出现问题:字段长度具有字段中分配的字符的长度。 这是类:

class indexException:public std::exception
{
    public:
    virtual const char* what()
    {
        return "Index is either too long, or negative";
    }
};

class string
{
    public:
    static const unsigned int length_max=100;
    string(const char* field=NULL)
    {
        if(field!=NULL)
        {
            const unsigned int length=strlen(field);
            this->field=new char[length+1];
            this->length=length;
            for(unsigned int i=0;i<=length;i++)
                this->field[i]=field[i];
        }
        else
        {
            this->field=NULL;
            length=0;
        }
    }
    string(string& str)
    {
        string(str.field);
    }
    ~string()
    {
        if(length>0)
            delete field;
    }
    char& operator[] (int i) const throw()
    {
        try
        {
            if(i<0 || i>=(int)length)
                throw indexException();
        }
        catch(indexException& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return field[i];
    }
    string& operator=(const char* field)
    {
        const unsigned int length=strlen(field);
        if(this->length>0)
            delete this->field;
        this->field=new char[length];
        this->length=length;
        for(unsigned int i=0;i<length;i++)
            this->field[i]=field[i];
        return *this;
    }
    string& operator= (const string& str)
    {
        if(this!=&str)
            *this=str.field;
        return *this;
    }
    operator char* ()
    {
        return field;
    }
    friend std::ostream& operator<< (std::ostream& out, string& str);
    friend std::istream& operator>> (std::istream& in, string& str);
    public:
    unsigned int length;
    char* field;
};

std::ostream& operator<<(std::ostream& out, string& str)
{
    out << str.field;
    return out;
}

std::istream& operator>> (std::istream& in, string& str)
{
    char temp[string::length_max];
    in >> temp;
    str=temp;
    return in;
}

如果我使用赋值运算符,这不会导致段错误。 但它间接地导致了它。 我解释如何:

int main(int argc,char** argv)
{
    string str="hi";
    string str2=str;
    return 0;
}

在赋值运算符重载中设置断点,我意识到赋值运算符不会导致段错误。 问题是在退出 main 之后。 如果我删除析构函数,我就不会遇到这个段错误,但我会知道为什么会遇到这个问题。

编辑:我明白问题出在哪里了。 我听从了你的建议,但它仍然会出现段错误。 但是现在它不再在析构函数方法上崩溃,而是在赋值运算符重载上崩溃:

    string& operator=(const char* field)
    {
        unsigned int length=0;
        if(field!=NULL)
            length=strlen(field);
        else
            field="";
        if(this->length>0)
            delete[] this->field;
        this->field=new char[length+1];
        this->length=length;
        strcpy(this->field,field);
        return *this;
    }

问题是当我删除这个->字段时,调试器停在那里。 段错误示例:

string str("hi");
string str2=str;

这会导致段错误。我认为这是因为 str2 未初始化,并且 length 具有未定义的值。 如果我改为这样做:

string str("hi");
string str2;
str2=str;

没有任何段错误。为什么? 我认为调用:

string str2;

也是在调用构造函数,还是“=”运算符有优先权? 如何解决?

PS:我还改变了其他东西,比如复制构造函数。 完整代码在这里: http://pastebin.com/ubRgaVr8

已解决:我按照接受的回复中的建议更改了复制构造函数:

    string(const string& str)
    {
        length=str.length;
        field=new char[str.length+1];
        memcpy(field,str.field,length+1);
    }

最佳答案

你的复制构造函数没有初始化对象。

string(string& str)
{
    string(str.field); // Does nothing
}

string(str.field)创建一个未命名 string并立即将其丢弃。 它不会使用不同的构造函数初始化此对象。

由于您的对象现在只包含随机性,因此当您尝试销毁它时会发生不好的事情。

为了确保事情被初始化,创建一个私有(private)成员函数

void initializeFromChars(const char* cString);

完成工作并在您的构造函数和赋值运算符中使用它。

关于c++ - 导致段错误的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9337423/

相关文章:

c++ - QPlainTextEdit - 搜索文档到最后,然后再从头开始

c++ - 查找整数值计数的最快方法 (C++)

重新部署为 Web 应用程序时,ClassLoader 出现 Java JNI GDAL native 库错误

c++ - 来自 glClear() 的 OpenGL 帧缓冲区错误

c++ - 如何理解is_callable的定义?

c++ - 使 C++ 中的类成为全局应用程序

c++ - 为什么需要在编译时知道对象的内存配置文件以进行堆栈放置?

c++ - 选择安装的网络浏览器

c++ - 如何在 C++ 中显示项目计数对列表?

c++ - 如何确定 catch (...) block 中的当前异常?