【问题标题】:Destructor crashing when deleting an array of pointers in C++在 C++ 中删除指针数组时析构函数崩溃
【发布时间】:2018-01-03 05:02:48
【问题描述】:

我创建了一个名为cell 的类。在这个类中有一个cell 指针数组。标题如下所示:

class cell
{       
 public:
  cell();
  cell *c[8];
  void creatcells();
  virtual ~cell();
  ..

}

cpp 文件如下所示:

cell::cell()
{
//ctor
 for(int i=0;i<8;i++)
 {
   c[i]=NULL;
 }

}


void cell::creatcells()

 {
   cell c1,c2,c3,c4,c5,c6,c7,c8;

   c[0]=&c1;
   c[1]=&c2;
   c[2]=&c3;
   c[3]=&c4;
   c[4]=&c5;
   c[5]=&c6;
   c[6]=&c7;
   c[7]=&c8;
 }

cell::~cell()
{
    for(int i=0; i<8; i++)
    {
        if (c[i]!=NULL)
        {
                    delete c[i];
        }
    }
    delete[] c;

 }

但是每次程序结束,它都会崩溃,为什么?
我试过没有if (c[i]!=NULL),但这没有帮助。只有没有 for 循环,代码才能完美结束,但我知道这也必须删除。 我认为我正确地编写了析构函数,不是吗?

【问题讨论】:

  • 用调试器打开程序,它会在崩溃点中断
  • cell c1,c2,c3,c4,c5,c6,c7,c8;
  • c1、c2 等变量都不存在于函数createcells 的范围之外。所以存储指向它们的指针会导致你有一个充满悬空指针的数组。
  • delete [] c 也未定义。

标签: c++ crash destructor delete-operator


【解决方案1】:
void cell::creatcells()
 {
   cell c1,c2,c3,c4,c5,c6,c7,c8;

   c[0]=&c1;
   c[1]=&c2;
   ...

上面所有的cell对象都会在createcells()的末尾自动销毁。所以delete c[i];在析构函数中就是UB。你想要的是

 c[0]= new cell();
 c[1]= new cell();

【讨论】:

  • 您真正想要的是std::vector&lt;cell&gt; 和返回值优化!
  • 这样做,我是否必须像以前一样删除它们?或者他们被摧毁了?我按照您的建议更改了代码,并像以前一样保留了我的析构函数,但它又崩溃了......
  • @NoamChai delete[] c; 你不需要这个,因为你已经删除了循环中的所有对象。
  • @GauravSehgal delete[] c 未定义,所以我认为“不需要”是轻描淡写。
【解决方案2】:

您正在尝试取消引用指向和delete 变量的指针,这些变量具有自动存储持续时间并且不再在范围内!你的编译器没有警告你吗?

因此,您的程序的行为是未定义的。

您只能永远将delete[] 与new[] 和delete 与new 配对;尽管您可以将 delete(甚至是 new1)委托给像 std::unique_ptr 这样的托管指针类。

为什么不重构为std::vector&lt;cell&gt; 并利用返回值优化?


1使用std::make_unique。

【讨论】:

  • @MartinBonner:谢谢,请注意。
【解决方案3】:

在cell::createcells 函数中,变量是本地 并且超出范围并在函数返回后被破坏。当您尝试删除它们时,这些对象将不存在。取消引用这些指针将导致undefined behavior。

更不用说你应该只delete 你new。而且由于您没有在new 上对指针进行任何delete 操作再次 导致undefined behavior。

简单的解决方案是使用一个vector 的对象:

std::vector<cell> c;

然后简单地将八个 cell 对象添加到向量中:

void cell::creatcells()
{
    c = std::vector<cell>(8);
}

现在向量将包含八个默认构造的cell 对象。无需在构造函数或析构函数中做任何事情。事实上,我建议你完全按照the rule of zero删除构造函数和析构函数。

【讨论】:

    猜你喜欢
    • 2012-03-13
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2014-12-30
    • 2021-10-12
    相关资源
    最近更新 更多