On Tue, 04 Dec 2018 15:14:40 +0100, Alf P. Steinbach wrote:
> On 04.12.2018 14:53, Markus Moll wrote:
>> Accessing any non-static members of an object whose lifetime has ended
>> is undefined behavior.
>
> No. The formal lifetime ends with start of the destructor execution (if
> any). But:
>
> C++17 §15.7/1 [quote]
> For an object with a non-trivial destructor, referring to any non-static
> member or base class of the object after the destructor finishes
> execution results in undefined behavior.
> [/quote]
>
> I.e. you're safe. :)
>
Hm, I agree that accessing the sub-objects is safe (which is what I rely
on in my revised code example). However, the problem seems to be
accessing them through a pointer to A, as 3.8 states:
[quote]
(...) after the lifetime of an object has ended and before the storage
which the object occupied is reused or released, any pointer that refers
to the storage location where the object will be or was located
may be used but only in limited ways. (...) 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
[/quote]
And yes, I think it would be safe to store a pointer to the atomic<bool>
in the thread and use that pointer. However, I would prefer not to do
that. Background: the thread in my example is a timer thread. Users can
add or remove timer callbacks of type "void (*)(void*)". I follow the
familiar pattern of using a static member with that signature which
converts its argument to A* and then calls a corresponding non-static
member function without further arguments. That call, in my opinion,
would be undefined behavior. (And I find that both odd and surprising)
Markus