创建'new'实例可以解决析构函数崩溃问题?

Creating a 'new' instance solves destructor crash?

本文关键字:析构函数 崩溃 解决 问题 new 实例 创建      更新时间:2023-10-16

我创建了一个子类B,用于我称为a。

的类

我为工作编写了此代码,所以我将概括实际的代码:

class A
{
public:
  A ()
     {
     important_variable = new Type();
     ...
     };
  ~A (void) { delete(important_variable); };      // Default destructor
  // more methods
protected:
  Type        *important_variable;
};
class B : public A
{
public:
B() : A() { important_variable = another_var; }
~B() {};
Type *another_var;
};

为B提供此代码,导致我的程序崩溃了,而"未经治疗的异常"。

现在,当我将B类代码更改为此:

class B : public A
{
public:
B() : A() { another_var = new Type(); important_variable = another_var; }
~B() {};
Type *another_var;
};

例外消失了。

我认为我的原始代码导致我的程序崩溃,因为A试图删除一个仍被另一个变量指向的变量。这是正确的吗?为什么B的新代码导致我的程序工作?

您的代码中有许多缺陷,但是最有可能导致崩溃的一个缺陷是:

important_variable = another_var;

another_var不能指向可以删除的任何地方。但是important_variable是指向同一位置,然后在A的构造器中删除。

您的"解决方案"以内存泄漏为代价掩盖了问题。当您这样做

another_var = new Type(); important_variable = another_var;

important_variable指向的原始动态分配的Type对象丢失了。

除此之外,您还需要遵循三个规则。

新的和删除仅用于处理堆分配。我怀疑在您的第一次列表中,another_var可能分配在堆栈上,这就是导致灾难中例外的原因。此外,每当您有基础课时,您都应该制作其destructor virtual

原始版本崩溃了,因为您将important_variable设置为非初始化的another_var,然后尝试删除此非初始化值。在"校正"版本中,您至少不会删除非初始化的变量,但仍包含内存泄漏 - 您将新分配的内存分配给important_variable,然后立即分配给此变量another_var的值,因此最初分配的内存不再是可访问并将泄漏。