Re[4]: Безопасно ли присваивать один указатель другому?..
От: okman Беларусь https://searchinform.ru/
Дата: 24.03.18 04:15
Оценка:
Здравствуйте, Croessmah, Вы писали:

C>Если я правильно понял, то Вы наткнулись на неопределенное поведение при преобразовании указателей:

C>...

Спасибо, именно эта цитата все объясняет:

To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a
pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction
of all of its direct or indirect bases that directly or indirectly derive from B shall have
started and the destruction of these classes shall not have completed, otherwise the conversion
results in undefined behavior.


C>То есть для Вашего случая сначала необходимо сделать преобразование (присваивание) пока объект не уничтожен, и только затем удалять объект:

C>...

Похоже, что разработчики библиотек в курсе про этот нюанс. Вот нашел в исходниках
Boost 1.66.0 следующий комментарий (/boost/smart_ptr/weak_ptr.hpp):
//
//  The "obvious" converting constructor implementation:
//
//  template<class Y>
//  weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
//  {
//  }
//
//  has a serious problem.
//
//  r.px may already have been invalidated. The px(r.px)
//  conversion may require access to *r.px (virtual inheritance).
//
//  It is not possible to avoid spurious access violations since
//  in multithreaded programs r.px may be invalidated at any point.
//

Судя по всему, они подразумевают примерно такой кейс:
shared_ptr<X1> ptr = ...;
weak_ptr<X1> w1(ptr);
ptr.reset();
weak_ptr<Base> w2(w1); // BANG!

Глянул реализацию std::weak_ptr в VS2015 — там тоже учтен этот момент.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.