VS7.1 Программа "падает" при удалении класса.
От: Tujh Голландия  
Дата: 22.09.07 15:39
Оценка: :))
Удалось, с грехом пополам, локализовать баг.
Структура кода следующая

class Base
{
    public:
        Base()
        {
            std::cout << "class Base create" << std::endl;
        };

        virtual ~Base()
        {
            std::cout << "class Base destroy" << std::endl;
        };

        void Destroy()
        {
            delete this;
        };
};

class Child: public Base
{
    public:
        Child()
        {
            std::cout << "class Child create" << std::endl;
        };

        virtual ~Child()
        {
            std::cout << "class Child destroy" << std::endl;
        };
};

Вроде все как обычно, но вот удалять классы хотелось бы при вызове Destroy()
Если делаю вот так — все работает:
int main(int argc, char* argv[])
{
    Child *pClass = new Child;
    pClass->Destroy();
    getch();
    return 0;
};


А если так — приложение "падает"
int main(int argc, char* argv[])
{
    Child pClass;
    pClass.Destroy();
    getch();
    return 0;
};

Выпадает сообщение:

Debug Assertion Failed!

Program: C:\Project\Source\Cpp\test\this\Debug\this.exe
File: dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)


В консоль выводится как и положено:
class Base create
class Child create
class Child destroy
class Base destroy


Дебагером нашел, что "падает" потому, что в функцию delete передается неправильный pHead, точнее вообще какой-то "левый".
Кто-нибудь сталкивался с таким поведением, или я неправильно предположил, что по delete this можно удалить дочерний класс (хотя, если судить по вызываемым деструкторам — все работает как и задумывалось)
Re: VS7.1 Программа "падает" при удалении класса.
От: den123 Израиль http://den123.smugmug.com
Дата: 22.09.07 15:51
Оценка: -2
Здравствуйте, Tujh, Вы писали:

T>Удалось, с грехом пополам, локализовать баг.

T>Структура кода следующая

T>
class Base
T>{
T>    public:
T>        Base()
T>        {
T>            std::cout << "class Base create" << std::endl;
T>        };

T>        virtual ~Base()
T>        {
T>            std::cout << "class Base destroy" << std::endl;
T>        };

T>        void Destroy()
T>        {
T>            delete this;
T>        };
T>};

T>class Child: public Base
T>{
T>    public:
T>        Child()
T>        {
T>            std::cout << "class Child create" << std::endl;
T>        };

T>        virtual ~Child()
T>        {
T>            std::cout << "class Child destroy" << std::endl;
T>        };
T>};

T>Вроде все как обычно, но вот удалять классы хотелось бы при вызове Destroy()
T>Если делаю вот так — все работает:
T>
int main(int argc, char* argv[])
T>{
T>    Child *pClass = new Child;
T>    pClass->Destroy();
T>    getch();
T>    return 0;
T>};


T>А если так — приложение "падает"

T>
int main(int argc, char* argv[])
T>{
T>    Child pClass;
T>    pClass.Destroy();
T>    getch();
T>    return 0;
T>};

T>Выпадает сообщение:

T>
Debug Assertion Failed!

T>Program: C:\Project\Source\Cpp\test\this\Debug\this.exe
T>File: dbgdel.cpp
T>Line: 52

T>Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)


T>В консоль выводится как и положено:

T>
class Base create
T>class Child create
T>class Child destroy
T>class Base destroy


T>Дебагером нашел, что "падает" потому, что в функцию delete передается неправильный pHead, точнее вообще какой-то "левый".

T>Кто-нибудь сталкивался с таким поведением, или я неправильно предположил, что по delete this можно удалить дочерний класс (хотя, если судить по вызываемым деструкторам — все работает как и задумывалось)

Во втором случае объект удалается дважды! Первый раз в вашем коде
pClass.Destroy();

и второй раз "компилятором" при выходе из функции main.

Так что все верно....
WBR — Yuriy
Re[2]: VS7.1 Программа "падает" при удалении класса.
От: Tujh Голландия  
Дата: 22.09.07 16:05
Оценка:
Здравствуйте, den123, Вы писали:

D>Здравствуйте, Tujh, Вы писали:

D>Во втором случае объект удалается дважды! Первый раз в вашем коде
D>
D>pClass.Destroy();
D>

D> и второй раз "компилятором" при выходе из функции main.
D>Так что все верно....
Точно, не подумал об этом. Огромное спасибо !
Re[3]: VS7.1 Программа "падает" при удалении класса.
От: Sni4ok  
Дата: 22.09.07 16:21
Оценка: :)
Здравствуйте, Tujh, Вы писали:

D>> и второй раз "компилятором" при выходе из функции main.

D>>Так что все верно....
T>Точно, не подумал об этом. Огромное спасибо !

заюзайте инплэйс конструктор, и во втопром случае падать не будет)
Re: VS7.1 Программа "падает" при удалении класса.
От: Аноним  
Дата: 22.09.07 16:34
Оценка:
Здравствуйте, Tujh, Вы писали:

T>Дебагером нашел, что "падает" потому, что в функцию delete передается неправильный pHead, точнее вообще какой-то "левый".

T>Кто-нибудь сталкивался с таким поведением, или я неправильно предположил, что по delete this можно удалить дочерний класс (хотя, если судить по вызываемым деструкторам — все работает как и задумывалось)

Нельзя удалять объект выделенный на стеке через delete.
Re[2]: VS7.1 Программа "падает" при удалении класса.
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 22.09.07 17:14
Оценка: 1 (1) +3
Здравствуйте, den123, Вы писали:

D>Во втором случае объект удалается дважды! Первый раз в вашем коде

D>
D>pClass.Destroy();
D>

D> и второй раз "компилятором" при выходе из функции main.

На самом деле проблема возникает еще раньше: в строке
pClass.Destroy();

Дело в том, что выражение 'delete this' сначала вызывет деструктор, а потом попытается освободить память посредством вызова operator delete. Потому как память для объекта выделена на стеке, попытка ее освобождения через operator delete приведет к UB.

Если тебе действительно необходимо удалять классы через Destoy(), можешь сделать так:
class Base
{
public:
    void Destroy() { this->~Base(); }
private:
    ~Base() { }
};

Закрытый конструктор не позволит создать объект на стеке, 'this->~Base()' вместо 'delete this' позволяет корректно создавать объект через placement new.
-- Андрей
Re: VS7.1 Программа "падает" при удалении класса.
От: Анатолий Широков СССР  
Дата: 22.09.07 18:15
Оценка:
T>Кто-нибудь сталкивался с таким поведением, или я неправильно предположил, что по delete this можно удалить дочерний класс (хотя, если судить по вызываемым деструкторам — все работает как и задумывалось)

Правило простое: удаляй с помощью delete ([]) только то, что выделил с помощью new ([]).
Re[3]: Это всё, конечно, очень интересно...
От: Erop Россия  
Дата: 23.09.07 20:03
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Если тебе действительно необходимо удалять классы через Destoy(), можешь сделать так:


АК>Закрытый конструктор не позволит создать объект на стеке, 'this->~Base()' вместо 'delete this' позволяет корректно создавать объект через placement new.



Это всё, конечно, очень интересно, и правильно, но, возможно, не совсем доступно топикстартеру
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Это всё, конечно, очень интересно...
От: Smal Россия  
Дата: 24.09.07 06:19
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Если тебе действительно необходимо удалять классы через Destoy(), можешь сделать так:


АК>>Закрытый конструктор не позволит создать объект на стеке, 'this->~Base()' вместо 'delete this' позволяет корректно создавать объект через placement new.


E>Это всё, конечно, очень интересно, и правильно, но, возможно, не совсем доступно топикстартеру


И что ты предлагаешь? Не объяснять, а постать топикстартера читать страуструпа (или стандарт) до поси... тьфу осознания?
Это, конечно, правильно (так и надо ), но как-то грубо .
С уважением, Александр
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.