C++ Logo


Advanced search

Re: CWG710 and races during object construction

From: Jason Cobb <jason.e.cobb_at_[hidden]>
Date: Thu, 11 Feb 2021 23:17:08 -0500
On 2/11/21 10:01 PM, Giuseppe D'Angelo via Std-Discussion wrote:
> Hi,
> Il 11/02/21 19:25, Jason Cobb via Std-Discussion ha scritto:
>> Right, if it happened-before the end of the constructor (when not in the
>> "Otherwise" case), [0] applies. But if it doesn't happen-before the end
>> of the constructor, [1] still applies.
>> (Disclaimer: I'm an idiot and this could all be very wrong.)
>> [0]:https://eel.is/c++draft/class.cdtor#5.sentence-2
>> [1]:https://eel.is/c++draft/basic.life#7.4
> In other words, are you suggesting that the part about "For an object
> under construction or destruction" is about establishing two
> happens-before relationships -- beginning of construction happens-before
> the usage of the glvalue, and such usage happens-before end of
> construction -- without which we're falling into the "Otherwise" case?
> (Sure, it's a possible reading; but then I'd claim that the text
> should've also properly used "before" and "after" instead of "under", as
> per the defect resolution...)

I don't think this is a big deal under my reading, though it is probably
a minor wording issue either way.

> However, it begs further clarifications:
> 1) does "object" in the sentence refer to the complete object or to each
> and every subobject being constructed? The entire section seems to refer
> to complete objects, in fact Note 1 refers to [class.base.init] for
> discussing the lifetime of subobjects.
>> https://eel.is/c++draft/basic.life#3
> If that's the case (complete object), then I'd say there's still a problem:
> std::thread t;
> struct B {
> B() { t = std::thread([&]{ typeid(*this); });
> virtual ~B();
> };
> struct D : B {
> D() { t.join(); }
> } d;

*laughs nervously*

I'm not sure - this is a good test case. [basic.life]/7 applies because
*this could be a glvalue for an object whose lifetime has not started,
but I don't think that gets us to UB. You may want to ask someone who
knows more than me and/or file a core issue.

> 2) does this also mean that this is UB?
> struct S {
> S() { std::thread([&]{ this->f(); }).detach(); }
> void f();
> } s;
> We would be in the "Otherwise" case and triggering 7.2
>> https://eel.is/c++draft/basic.life#7.2
> ?

Yes, I think this must be UB because the member function call races with
the destruction of s. It could be UB by another clause (either instead
of this clause or in addition to another clase), but I think this clause
could reasonably make it UB.

Jason Cobb

Received on 2021-02-11 22:17:13