Full name of submitter (unless configured in github; will be published with the issue): Jim X
[intro.races] p2 says:
Two expression evaluations conflict if one of them
and the other one
- 2.3 reads or modifies the same memory location or
- 2.4 starts or ends the lifetime of an object occupying storage that overlaps with the memory location.
The definition of a memory location is
A memory location is the storage occupied by the object representation of either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width.
Consider this example:
#include <string>
#include <thread>
alignas(std::string) unsigned char buffer[sizeof(std::string)];
auto ptr = new (buffer) std::string{};
int main() {
std::jthread t1([]() {
new (buffer) char{}; // #1
});
std::jthread t2([]() {
auto r = ptr->size(); // #2
});
}
In this example, #1 is an evaluation that starts the lifetime of an object in a memory location called L. #2 is an evaluation that reads the string object. In [intro.races] p2, only bullet 2.3 mentions reading a memory location, that is, only 2.3 can apply to #2, therefore, 2.2 applies to #1.
However, std::string is a type whose private members are opaque. We don't know whether a std::string object comprises a scalar member object in the memory location L, such that the read to std::string will read the scalar object, which will conflict with #1.
In addition, consider another example:
#include <thread>
alignas(int) unsigned char buffer[8];
int main() {
auto ptr = new (buffer) int{};
std::jthread t1([&]() {
new (buffer) char{}; // #1
});
std::jthread t2([&]() {
auto n = *ptr; // #2
});
}
Similarly, only 2.3 can apply to #2; #1 starts the lifetime of an object of type char in memory location L. However, the size of the object of type int is larger than int. In this case, can we say that reading a larger memory location reads the same memory location as L?
Suggested Resolution:
Change 2.3 bullet to
reads or modifies a memory location that overlaps with the above-mentioned memory location or
Full name of submitter (unless configured in github; will be published with the issue): Jim X
[intro.races] p2 says:
The definition of a memory location is
Consider this example:
In this example,
#1is an evaluation that starts the lifetime of an object in a memory location calledL.#2is an evaluation that reads the string object. In [intro.races] p2, only bullet2.3mentions reading a memory location, that is, only2.3can apply to#2, therefore,2.2applies to#1.However,
std::stringis a type whose private members are opaque. We don't know whether astd::stringobject comprises a scalar member object in the memory locationL, such that the read tostd::stringwill read the scalar object, which will conflict with#1.In addition, consider another example:
Similarly, only
2.3can apply to#2;#1starts the lifetime of an object of typecharin memory locationL. However, the size of the object of typeintis larger thanint. In this case, can we say that reading a larger memory location reads the same memory location asL?Suggested Resolution:
Change
2.3bullet to