C ++:在派生类对象被破坏时释放动态内存

时间:2016-03-26 12:20:45

标签: c++ debugging error-handling dynamic-memory-allocation heap-corruption

我似乎遇到动态内存分配问题。

在下面,您将看到一个派生类,其中包含将使用void name(const char* name)方法动态分配的名称变量的指针。该函数由Product构造函数运行,该构造函数在创建对象时为产品类设置名称。这是班级:

namespace sict {
  class Product :public Streamable {

    char* name_;

public:

    Product(const char* name);
    virtual ~Product();

    void name(const char* name);

}

这里有名称函数本身,以及一个参数构造函数:

void sict::Product::name(const char * name) {
    int g = strlen(name);
    name_ = new char[g];
    strncpy(name_, name, g);
    name_[g] = 0;
}

Product::~Product() {
    delete [] name_;
    name_ = nullptr;
}

对我来说,这个代码似乎足以创建对象,然后在它退出运行它的函数范围时安静地销毁它。但是,当函数结束并且析构函数运行时,程序会冻结/崩溃在delete [] name_。在Visual Studio的编译器上运行该程序似乎没有产生任何特定错误(程序冻结除外),但gcc编译器检测到某种堆损坏。有人会知道为什么会这样吗?

1 个答案:

答案 0 :(得分:3)

我不确定为什么Sean Cline没有发表评论作为答案,但肖恩是正确的。

name_被赋予g个元素,然后name_[g]被设置为零,但name_[g]是一个超过数组末尾的元素。使用name_ = new char[g+1];name_[g-1] = 0;,这样就不会超过数组的末尾。

另外,正如几条评论所指出的,每当你有一个动态分配内存的类时,请确保定义复制构造函数赋值运算符,以及的即可。如果您错过了一个,默认实现将执行浅拷贝,这可能会让您感到头痛。

浅拷贝是复制指针而不是指向的数据。在你的情况下,如果复制或分配了这个类的对象,你最终会得到两个指向堆上相同数据的对象,并且当它们运行析构函数时它们都会尝试删除它。

有关这些功能的更多信息,请参阅Rule of Three