2013-08-02 4 views
0
int main() 
{ 
    myClass obj; 

    .... /* doing things */ 
    .... 

    delete &obj; /* illegal */ 
} 

Предположим, что myClass является подходящим классом C++ со всем на месте. Теперь я знаю, что это незаконно, и эта программа выйдет из строя во время выполнения. Дело в том, что код пытается удалить объект стека, а затем, после завершения области, он снова будет уничтожен. Я хочу знать внутренности этой незаконной операции. то есть что произойдет с удалением, вызовет ли он деструктор? Это может показаться вам безумным, но, пожалуйста, помогите мне понять.Незаконное удаление объекта стека

+4

Это будет * возможно, сбой, но, как и в случае с неопределенным поведением, он может, с другой стороны, не сбой или сбой большую часть времени, но не всегда, или даже вызвать [носовые демоны] (http://www.catb.org/jargon/html/N/nasal-demons.html). Более подробно о вашем вопросе, на самом деле нет способа рассказать, как это будет обрабатываться, характер неопределенного поведения в большинстве случаев непредсказуем. –

+1

Нетрудно узнать, что он на самом деле делает, проверяя сгенерированный код в неоптимизированных сборках. – sehe

+1

Это не обман. ОП здесь не спрашивает, безопасно ли это, они знают, что это не так. – jrok

ответ

2

Вам не хватает одной важной вещи - кроме вызова деструктора, delete освободит память, выделенную new, и она вернет ее в кучу. Вызов свободной по стеку выделенной переменной небезопасен. Чтобы увидеть, вызовет ли он сначала деструктор, просто введите cout внутри myClass destructor - в моей конфигурации он вызывает деструктор перед ошибкой сегментации.

#include <iostream> 

using namespace std; 

class myClass 
{ 
public: 
    ~myClass(){ cout << "Destructor" << endl; } 

}; 


int main() 
{ 
     myClass A; 
     delete &A; 
     cout << "End of main\n"; 
     return 0; 
} 

От MSDN:

Когда удаление используется для освобождения памяти для ++ объект класса C, деструктор объекта вызывается перед памятью объекта освобождается (если объект имеет деструктор).

0

правило:

Для каждого new должно быть ровно один delete.
Для каждого new[] должно быть ровно одно delete[].
Для каждого malloc или calloc должно быть ровно одно free.
Для каждого объекта stack allocated не должно быть явного удаления.

Все остальное будет вызывать неопределенное поведение.


то, что будет происходить со стиранием, это будет вызывать деструктор?

Да, удалить сначала вызовет объекты деструктора.

6

Поведение не определено. То, что произойдет, будет зависеть от деталей класса, от того, что еще происходит, от того, как реализован диспетчер памяти программы, какой вы использовали компилятор, о какой системе вы работаете и, возможно, о множестве других вещей, которые у меня нет заняло время, чтобы подумать. Это в значительной степени напоминает просьбу о деталях того, что происходит, когда взрывается химический резервуар для хранения.

1

Это неопределенное поведение.Стандарт, слова, по которым мы все живем и смотреть до, говорит:

В противном случае значение подается оператор удаления (недействительный *) в стандартной библиотеке должен быть одним из значений, возвращаемых предыдущими вызова либо оператор новый (size_t) или оператор нового (size_t, Const станда :: nothrow_t &) в стандартной библиотеке

Так что это неопределенное поведение, все может случиться, и это будет зависеть от реализации объект ошибочно удален, компилятор, удача и другие вещи. Просить «что происходит» внутренне не имеет смысла, потому что все может случиться. Скорее всего, поскольку оператор delete предполагает, что вы используете его правильно, вы в конечном итоге вводите некоторые непредсказуемые изменения в стеке, которые могут что-то испортить. Возможно, ваш предыдущий указатель кадра перезаписывается, возможно, какое-то смехотворное возвращаемое значение попадает в функцию, возможно, сохраненные регистры перезаписываются, поэтому попытка восстановить состояние регистра приводит к очень нелегальной ситуации. Что бы ни случилось, это уродливо.

Смежные вопросы