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

C++: Deallocating dynamic memory when derived class object is destructed

我似乎对动态内存分配有疑问。

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

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;
}

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

我不确定为什么 Sean Cline 没有 post 他的评论作为答案,但 Sean 是正确的。

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

此外,正如一些评论所指出的,任何时候你有一个动态分配内存的class,确保你定义了复制构造函数赋值运算符,以及析构函数。如果您错过了一个,默认实现将执行 浅拷贝,这会让您头疼。

A 浅拷贝是指针被拷贝而不是它指向的数据。在你的例子中,如果这个 class 的一个对象被复制或分配,你最终会得到两个指向堆上相同数据的对象,并且它们都会在 运行 时尝试删除它他们的析构函数。

有关这些函数的详细信息,请参阅 Rule of Three