This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-08-20
[Voted into WP at March, 2010 meeting.]
Consider the following example:
struct A { A() { std::thread(&A::Func, this).detach(); } virtual void Func() { printf("In A"); } }; struct B : public A { virtual void Func() { printf("In B"); } }; struct C : public B { virtual void Func() { printf("In C"); } }; C c;
What is the program allowed to print? Should it be undefined behavior or merely unspecified which of the Func()s is called?
There is a related question about which variables C::Func() can depend on having been constructed. Unless we want to require the equivalent of at least memory_order_consume on the presumed virtual function table pointer, I think the answer is just the members of A.
If I instead just have
A a;
I think the only reasonable behavior is to print In A.
Finally, given
struct F { F() { std::thread(&F::Func, this).detach(); } virtual void Func() { print("In F"); } }; struct G : public F { }; G g;
I can see the behavior being undefined, but I think a lot of people would be confused if it did anything other than print In F.
Suggested resolution:
I think the intent here is that an object should not be used in another thread until any non-trivial constructor has been called. One possible way of saying that would be to add a new paragraph at the end of 11.9.5 [class.cdtor]:
A constructor for a class with virtual functions or virtual base classes modifies a memory location in the object that is accessed by any access to a virtual function or virtual base class or by a dynamic_cast. [Note: This implies that access to an object by another thread while it is being constructed often introduces a data race (see 6.9.2 [intro.multithread]). —end note]
Proposed resolution (October, 2009):
Add the following as a new paragraph at the end of 6.7.3 [basic.life]:
In this section, “before” and “after” refer to the “happens before” relation (6.9.2 [intro.multithread]). [Note: Therefore, undefined behavior results if an object that is being constructed in one thread is referenced from a different thread without adequate synchronization. —end note]