Оператор новый / удалить и деструкторы - PullRequest
1 голос
/ 19 января 2011

Итак, я новичок, пытающийся справиться с оператором new.Что не так с моим деструктором?

class arr{
public:
    arr(){
        pool=::operator new(100*sizeof(double));
    }
    ~arr(){
        ::operator delete(pool);
    }
    void* pool;
};

int main()
{
    arr a;
    a.~arr(); //If I comment this out it's ok.

    void* pool2=::operator new(100*sizeof(double)); //Works
    ::operator delete(pool2); //Fine.

    system("pause");
    return 0;
}

Выход из. ~ Arr ();В дает мне эту ошибку:

Отладка утверждение не удалось!Файл: dbgdel.cpp строка: 52

Выражение: _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

Я не могу понять, почему pool2 работает нормально, но использование класса вызывает у меня проблемы.Также ошибка появляется только после "пауз" системы, то есть после того, как. ~ Arr () вызывается ???

Спасибо!

Ответы [ 3 ]

7 голосов
/ 19 января 2011

Ну, на первый взгляд, вы не должны явно вызывать деструктор.Вместо этого используйте область действия, чтобы вывести объект из области видимости и вызвать деструктор.

int main()
{
    {
        arr a;
    } //This calls destructor of a

    //Rest of code
}

В противном случае деструктор вызывается дважды: один раз, когда вы вызываете его, и снова, когда объект выходит из области.

РЕДАКТИРОВАТЬ:

Здесь вы идете.

http://www.parashift.com/c++-faq-lite/dtors.html

6 голосов
/ 19 января 2011

Проблема в том, что вы явно вызываете деструктор на a (a.~arr()), в то время как деструктор уже будет автоматически вызываться , когда a выходит из области видимости. в конце main(). Когда деструктор вызывается во второй раз, он вызывается для уже разрушенного объекта . Технически это приводит к неопределенному поведению (что означает, что любой результат будет нормальным в соответствии со стандартом C ++). На практике этот код, скорее всего, просто снова выполнит деструктор, передав адрес, сохраненный в ячейке памяти, который раньше был a.pool, в ::operator delete() (который может быть, а может и не быть тем, что там хранится конструктор), который перехватывается время отладки.

Что вы должны сделать вместо этого, если хотите, чтобы a был удален в середине main(), это ввести дополнительную область:

int main()
{
  {
    arr a;
  } //a will be deleted here

  // rest of main

}

Другой способ - не использовать автоматический объект, а динамический, для которого вы можете установить время жизни.


Но есть другая проблема с вашим кодом, о которой вы не спрашивали, но на которую я все же чувствую необходимость указать:

Вашему классу срочно требуется конструктор копирования и оператор присваивания . (По крайней мере, объявите их private, чтобы запретить копирование.) В соответствии с Правилом Три , тот факт, что вам нужен деструктор, должен дать вам подсказку, что два других нужны, поскольку хорошо.
Вы можете избежать всех хлопот, не пытаясь вручную управлять динамически выделяемой памятью. Вместо этого используйте тип, который делает это за вас:

class arr{
public:
    arr() : pool(100*sizeof(double)) {

    }
    // ~arr() // not needed any longer
    std::vector<char> pool;
};
0 голосов
/ 19 января 2011

вам не нужно вызывать деструктор для объектов, созданных в стеке. Переменная 'a' находится в стеке и будет автоматически удаляться при выходе из области видимости.

...