cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2863 [basic.life] Lifetime races not properly handled: some "before" and "after" should be "not after" and "not before" because "happens before" is not a total order #507

Open zygoloid opened 4 months ago

zygoloid commented 4 months ago

Reference (section label): [basic.life]

Issue description:

In [basic.life], we find utterances such as:

  1. Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways.

and

  1. In this subclause, “before” and “after” refer to the “happens before” relation ([intro.multithread]).

But that doesn't work -- it doesn't properly handle the case of an evaluation that is racing with the start of the lifetime of an object. That's not a data race, because data races are concerned with a race between a modification and an access, and this paragraph is covering all uses, not only accesses.

What we mean is: if an evaluation happens after the storage which an object will occupy has been allocated, but does not happen after the lifetime of the object has started, then [...] any pointer [...] may be used but only in limited ways.

Suggested resolution:

Replace the "before" and "after" with "not after" and "not before" as appropriate (rephrasing as necessary so the wording is still grammatical). Eg:

  1. Before the lifetime of an object has started but In an evaluation that occurs after the storage which the an object will occupy has been allocated [footnote] but not after the lifetime of the object has started or, in an evaluation that occurs after the lifetime of an object has ended and before not after the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. Otherwise, such a pointer refers to allocated storage ([basic.stc.dynamic.allocation]), and using the pointer as if the pointer were of type void* is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if:

And likewise in /4, /7, /8.

jensmaurer commented 4 months ago

This seems wrong: "after the lifetime of an object has ended and not after the storage"

I think we want to leave "before" here, and not replace with "not after", because the user needs to prove (via happens-before) that the storage is still there.

jensmaurer commented 4 months ago

CWG2863

It's stupid to have the out-of-lifetime-but-within-storage conditions repeated twice over. Fixed with wording "option 2".

zygoloid commented 4 months ago

This seems wrong: "after the lifetime of an object has ended and not after the storage"

You're right, I changed the wrong half here.