Обнуление указателей в деструкторе
От: Peter K.  
Дата: 04.06.09 09:23
Оценка:
Иногда приходится нечто подобное:

class B;

class A {
   B * pb;
public:
   A() : pb(new B()) {}
   ~A()
   {
      delete pb;
      pb = 0;
   }
};

Насколько это pb = 0 может быть нужно и по какой причине?
(Извините, если уже было, не нашел).
Re: Обнуление указателей в деструкторе
От: nen777w  
Дата: 04.06.09 09:26
Оценка: +1 -1
Я тоже так делаю, хотя смысла это не имеет.
Ну разве что переменная будет статическая.
Re: Обнуление указателей в деструкторе
От: den123 Израиль http://den123.smugmug.com
Дата: 04.06.09 09:29
Оценка:
Здравствуйте, Peter K., Вы писали:

В данном случае нет никакого смысла обнулять, т.к. после деструктора уже ничего нет и последующее, ошибочное использование указателя уже будет невозможно
WBR — Yuriy
Re[2]: Обнуление указателей в деструкторе
От: Peter K.  
Дата: 04.06.09 09:49
Оценка:
Я когда-то читал, что так нужно в многопоточных программах.
Сейчас уже не вспомню где.
Re: Обнуление указателей в деструкторе
От: jazzer Россия Skype: enerjazzer
Дата: 04.06.09 09:55
Оценка: 1 (1) +1
Здравствуйте, Peter K., Вы писали:

PK>Иногда приходится нечто подобное:


PK>
PK>class B;

PK>class A {
PK>   B * pb;
PK>public:
PK>   A() : pb(new B()) {}
PK>   ~A()
PK>   {
PK>      delete pb;
PK>      pb = 0;
PK>   }
PK>};
PK>

PK>Насколько это pb = 0 может быть нужно и по какой причине?
PK>(Извините, если уже было, не нашел).

Это так народ пытается нейтрализовать двойной вызов деструктора
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Обнуление указателей в деструкторе
От: Bell Россия  
Дата: 04.06.09 10:01
Оценка: 1 (1) +3 -2
Здравствуйте, Peter K., Вы писали:

PK>Насколько это pb = 0 может быть нужно и по какой причине?

Абсолютно излишнее действие.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Обнуление указателей в деструкторе
От: Wo-o-olf Россия  
Дата: 04.06.09 10:17
Оценка: 1 (1) -1
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Peter K., Вы писали:


PK>>Иногда приходится нечто подобное:


PK>>
PK>>class B;

PK>>class A {
PK>>   B * pb;
PK>>public:
PK>>   A() : pb(new B()) {}
PK>>   ~A()
PK>>   {
PK>>      delete pb;
PK>>      pb = 0;
PK>>   }
PK>>};
PK>>

PK>>Насколько это pb = 0 может быть нужно и по какой причине?
PK>>(Извините, если уже было, не нашел).

J>Это так народ пытается нейтрализовать двойной вызов деструктора


Ну до кучи ещё может быть попытка нейтрализовать использование уже невалидного указателя на A.


A * a = new A();
a->SomeMethod(); // method uses A::pb
delete a;
a->SomeMethod();
Re[2]: Обнуление указателей в деструкторе
От: Аноним  
Дата: 04.06.09 10:25
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Peter K., Вы писали:


PK>>Насколько это pb = 0 может быть нужно и по какой причине?

B>Абсолютно излишнее действие.

Не излишнее, см пост выше. После того как память освободилась, она не обнуляется, и если у тебя остался указатель на кусок памяти, где раньше жил объект, то ты можешь достучатся до полей мертвого объекта (с непредсказуемыми последствиями в дальнейшем). А если обнулишь, то сразу будет АВ шка.
Re[2]: Обнуление указателей в деструкторе
От: R.O. Prokopiev Россия http://127.0.0.1/
Дата: 04.06.09 10:26
Оценка: -2 :)
Здравствуйте, Bell, Вы писали:

PK>>Насколько это pb = 0 может быть нужно и по какой причине?

B>Абсолютно излишнее действие.

Нифига подобного.
Действие очень даже нужное.
Деструктор можно вызывать явно:

    A a;
    a.~A();
    a.~A();
Re: Обнуление указателей в деструкторе
От: Кодт Россия  
Дата: 04.06.09 10:44
Оценка: 2 (2) +5
Здравствуйте, Peter K., Вы писали:

PK>Насколько это pb = 0 может быть нужно и по какой причине?


1) Перестраховка. Обращение к деструированному объекту — это уже UB, только характер может меняться.
Диагностировать обращение к неожиданно нулевому указателю легче, чем к невалидному указателю куда-то в середину кучи.
В крайнем случае, быстро поймаешь ошибку защиты памяти. В противном случае, проедешься с бензопилой по чужим данным.


2) Либо неудачный/бездумный рефакторинг.
Написали reset, а потом обнаружили, что он используется лишь в деструкторе. И скопировали туда.
Либо наоборот — собрались писать reset и забросили, так и не выделив из деструктора.


3) Либо это лишь часть кода. А на деле там всё громоздче:
class A
{
    .......
    B* pb;
    .......
    
    void foo()
    {
        .....
        if(pb) .....
        .....
    }

    ~A()
    {
        .....
        foo();
        .....
        delete pb; pb = 0;
        .....
        foo();
        .....
    }
};

В роли foo() могут быть обратные вызовы каких-то союзнических функций, работающих с этим объектом.
Например, у тебя облако взаимосвязанных объектов, и запускается лавина рекурсивного удаления их всех.
(На мой взгляд, лавины — это дыра в архитектуре, но на скорую руку, бывает, терпимо).
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[2]: Обнуление указателей в деструкторе
От: Peter K.  
Дата: 04.06.09 11:27
Оценка:
Понятно. Т.е. никакого сакрального смысла для многопоточных приложений здесь нет.
Обманули значит.
Re: Обнуление указателей в деструкторе
От: Аноним  
Дата: 04.06.09 11:45
Оценка:
PK>
PK>class B;

PK>class A {
PK>   B * pb;
PK>public:
PK>   A() : pb(new B()) {}
PK>   ~A()
PK>   {
PK>      delete pb;
PK>      pb = 0;
PK>   }
PK>};
PK>

PK>Насколько это pb = 0 может быть нужно и по какой причине?
PK>(Извините, если уже было, не нашел).

потому что кто нить потом может сделать например так:

class B;

class A {
   B * pb;
public:
   A() : pb(new B()) {}
   ~A()
   {
      delete pb;
      pb = 0;
      CleanupAll();
   }

   void CleanupAll()
   {
   ....
   pb->Cleanup();
   ...
   }
};

Tсли будет обнуление pb срузу после delete — то написанный кем то потом код сразу свалится в B::Cleanup() при обращении к данным/vftbl pb; А без обнуления будет UB — то бишь может свалится, может не свалится, может свалится потом, может свалится потом у каждого десятого юзера etc
Re[3]: Обнуление указателей в деструкторе
От: Bell Россия  
Дата: 04.06.09 12:24
Оценка:
Здравствуйте, R.O. Prokopiev, Вы писали:

B>>Абсолютно излишнее действие.


ROP>Нифига подобного.



ROP>Действие очень даже нужное.

Просвяти, в каких это случаях оно такое нужное?

ROP>Деструктор можно вызывать явно:

С этим никто не спорил
А вот обращение к полям разрушенного объекта — UB.

3.8/5
...
If the object will be or was of a non-POD class type, the program has undefined behavior if:
the pointer is used to access a non-static data member or call a non-static member function of the object

Любите книгу — источник знаний (с) М.Горький
Re[3]: Обнуление указателей в деструкторе
От: Кодт Россия  
Дата: 04.06.09 13:02
Оценка: +2
Здравствуйте, Peter K., Вы писали:

PK>Понятно. Т.е. никакого сакрального смысла для многопоточных приложений здесь нет.

PK>Обманули значит.

Видимо, те, кто тебя обманывал — пытались наобум исправить какой-то баг, связанный с гонками вокруг деструктора.
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[4]: Обнуление указателей в деструкторе
От: R.O. Prokopiev Россия http://127.0.0.1/
Дата: 04.06.09 14:12
Оценка:
Здравствуйте, Bell, Вы писали:

ROP>>Действие очень даже нужное.

B>Просвяти, в каких это случаях оно такое нужное?
Видел явный вызов деструктора в потрохах CArray
(еще в те времена когда не перешел на STL).
Глянул в VC8 — осталось.

Посмотрел в стандарт.
Признаться был не совсем прав.
Многократный вызов деструктора чреват UB.

12.4/14

Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the
destructor is invoked for an object whose lifetime has ended (3.8). [ Example: if the destructor for an automatic
object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined. ]

Re[5]: Обнуление указателей в деструкторе
От: R1K0 Россия  
Дата: 04.06.09 14:36
Оценка: -1
В принципе все уже сказано. Но все равно добавлю
Я, например, всегда так делаю, ибо AV отладить куда проще, особенно если мозги позволили добавить в рогу создание crash-dump'ов.
При наличие того другого отладка кривых ручек становится необычайно легкой (в сравннии с тем самым UB).
Ибо UB — это попытка доказать, что ты и не хотел быть программистом, а, так, случайно зашел
Re[2]: Обнуление указателей в деструкторе
От: Plague Россия  
Дата: 04.06.09 16:19
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Peter K., Вы писали:

PK>>Насколько это pb = 0 может быть нужно и по какой причине?

К>3) Либо это лишь часть кода. А на деле там всё громоздче:


Вот так хочешь людям поведать, где и почему оно может пригодится, а Кодт уже тут, как тут.
Думаю, что обнулять указатели стоит, даже в деструкторах. Вопрос лишь в том, не будет ли компилятор производить какие-либо оптимизации тут?
Re: Обнуление указателей в деструкторе
От: Аноним  
Дата: 04.06.09 19:32
Оценка:
Здравствуйте, Peter K., Вы писали:

PK>Насколько это pb = 0 может быть нужно и по какой причине?


Про то, что в случае проблем эти самые проблемы будет искать легче уже сказали.
Но лучше это дело автоматизировать и пользоваться умными указателями.
Re[3]: Обнуление указателей в деструкторе
От: Ulitka США http://lazarenko.me
Дата: 04.06.09 20:22
Оценка:
Здравствуйте, R.O. Prokopiev, Вы писали:

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


PK>>>Насколько это pb = 0 может быть нужно и по какой причине?

B>>Абсолютно излишнее действие.

ROP>Нифига подобного.

ROP>Действие очень даже нужное.
ROP>Деструктор можно вызывать явно:

ROP>
ROP>    A a;
ROP>    a.~A();
ROP>    a.~A();
ROP>


Можно, конечно. А можно и явно два раза "delete pb;" сделать, тоже никто не запрещает.
Re[6]: Обнуление указателей в деструкторе
От: Ulitka США http://lazarenko.me
Дата: 04.06.09 20:24
Оценка:
Здравствуйте, R1K0, Вы писали:

RK>AV отладить куда проще


А вот и нет. Точно так же просто, как и обращение к уже "удаленному" сегменту памяти.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.