Сбой деструктора при удалении массива указателей в C ++

Я создал класс с именем 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 код заканчивается отлично, но я знаю, что это тоже нужно удалить. Думаю, я правильно написал деструктор, не так ли?


person Noam Chai    schedule 27.07.2017    source источник
comment
Откройте программу с отладчиком, и она сломается в точке сбоя.   -  person user5821508    schedule 27.07.2017
comment
cell c1,c2,c3,c4,c5,c6,c7,c8; ‹- все это выходит за рамки в конце метода и адрес недействителен.   -  person crashmstr    schedule 27.07.2017
comment
Ни одна из переменных c1, c2 и т.д. не существует вне области действия функции createcells. Таким образом, хранение указателей на них приведет к тому, что у вас будет массив, полный висящих указателей.   -  person Cory Kramer    schedule 27.07.2017
comment
delete [] c также не определен.   -  person molbdnilo    schedule 27.07.2017


Ответы (3)


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();
person Gaurav Sehgal    schedule 27.07.2017
comment
Что вы действительно хотите, так это std::vector<cell> оптимизация возвращаемого значения! - person Bathsheba; 27.07.2017
comment
Должен ли я при этом удалить их, как делал раньше? или они уничтожены? Я изменил код, как вы предлагали, и сохранил свой деструктор, как и раньше, но он снова вылетает ... - person Noam Chai; 27.07.2017
comment
@NoamChai delete[] c; Вам это не нужно, так как вы уже удалили все объекты в цикле. - person Gaurav Sehgal; 27.07.2017
comment
@GauravSehgal delete[] c не определено, поэтому я думаю, что это не нужно, это преуменьшение. - person molbdnilo; 27.07.2017

Вы пытаетесь разыменовать указатели и delete переменные, которые имели автоматическую продолжительность хранения и больше не входят в область действия! Ваш компилятор не предупреждал вас об этом?

Следовательно, поведение вашей программы undefined.

Вы только когда-либо соединяете delete[] с new[] и delete с new; хотя вы можете делегировать delete (и даже new 1) классу управляемого указателя, например std::unique_ptr.

Почему бы вам не выполнить рефакторинг до std::vector<cell> и не использовать оптимизацию возвращаемого значения?


1 с использованием std::make_unique.

person Bathsheba    schedule 27.07.2017
comment
@MartinBonner: Спасибо, снял это. - person Bathsheba; 27.07.2017

В cell::createcells функции переменные являются локальными, выходят за пределы области видимости и уничтожаются после возврата из функции. Эти объекты не будут существовать, когда вы попытаетесь их удалить. Разыменовывание этого указателя приведет к неопределенному поведению.

Не говоря уже о том, что вы должны только delete то, что new. И поскольку вы не new ничего, делая delete указатели, снова приводит к неопределенное поведение.

Простое решение - использовать вектор объектов :

std::vector<cell> c;

Затем просто добавьте к вектору восемь cell объектов:

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

Теперь вектор будет содержать восемь построенных по умолчанию cell объектов. Не нужно ничего делать в конструкторе или деструкторе. Фактически, при этом я рекомендую вам полностью удалить конструктор и деструктор в соответствии с правилом нуля.

person Some programmer dude    schedule 27.07.2017