Title
Ambiguous status of access to non-live objects
Status
c++17
Section
[res.on.objects]
Submitter
Geoffrey Romer

Created on 2012-12-17.00:00:00 last changed 90 months ago

Messages

Date: 2015-05-05.19:13:23

Proposed resolution:

This wording is relative to N3485.

  1. Change the title of sub-clause [res.on.objects] as indicated:

    Shared objects and the libraryLibrary object access [res.on.objects]

  2. Edit [res.on.objects] p2 as indicated: [Editorial remark: The motivation, is to be more precise about the meaning of "outside the object's lifetime" in the presence of threads — end editorial remark]

    -2- [Note: In particular, the program is required to ensure that completion of the constructor of any object of a class type defined in the standard library happens before any other member function invocation on that object and, unless otherwise specified, to ensure that completion of any member function invocation other than destruction on such an object happens before destruction of that object. This applies even to objects such as mutexes intended for thread synchronization. — end note] If an object of a standard library type is accessed, and the beginning of the object's lifetime ([basic.life]) does not happen before the access, or the access does not happen before the end of the object's lifetime, the behavior is undefined unless otherwise specified. [Note: This applies even to objects such as mutexes intended for thread synchronization. — end note]

Date: 2015-05-05.19:13:23

[ 2014 Urbana ]

STL: is this resolved by our change to the reeentrancy rules? [LWG 2414]
GR: don't think that solves the multi-threaded case
MC: I like changing the note to normative text
GR: uses the magic "happens before" words, and "access" is magic too
JW: I like this. strict improvement, uses the right wording we have to say this properly
STL: I like the last sentence of the note, could we add that as a new note at the end?
So add "[Note: This applies even to objects such as mutexes intended for thread synchronization.]" to the end and move to Ready

Date: 2013-03-19.00:00:00

[ 2013-03-19 Geoffrey provides revised resolution and an example ]

I contend that the most straightforward reading of the current standard requires the following example code to print "good" (because ~unique_ptr is not specified to modify the state of the internal pointer), but the consensus on the reflector was that its behavior should be undefined.

This example also shows that, contrary to a comment in the telecon, the PR is not tautological. [class.cdtor]/p4 explicitly permits member function calls during destruction, so the behavior of this code is well-defined as far as the core language is concerned, despite the fact that it accesses a library object after the end of the object's lifetime. If we want this code to have undefined behavior, we need to specify that at the library level.

#include <memory>
#include <iostream>

class A;

struct B {
 std::unique_ptr<A> a;
};

struct A {
 B* b;
 ~A() {
   if (b->a.get() == this) {
     std::cout << "good" << std::endl;
   }
 }
};

int main() {
 B b;
 b.a.reset(new A);
 b.a->b = &b;
}

Previous resolution:

  1. Change the title of sub-clause [res.on.objects] as indicated:

    Shared objects and the libraryLibrary object access [res.on.objects]

  2. Edit [res.on.objects] p2 as indicated:

    -2- [Note: In particular, the program is required to ensure that completion of the constructor of any object of a class type defined in the standard library happens before any other member function invocation on that object and, unless otherwise specified, to ensure that completion of any member function invocation other than destruction on such an object happens before destruction of that object. This applies even to objects such as mutexes intended for thread synchronization. — end note] If an object of a standard library type is accessed outside of the object's lifetime ([basic.life]), the behavior is undefined unless otherwise specified.

Date: 2013-03-15.00:00:00

[ 2013-03-15 Issues Teleconference ]

Moved to Open.

Geoffrey will provide an example that clearly highlights the issue.

Date: 2012-12-17.00:00:00

The standard currently does not discuss when library objects may be accessed, except in a non-normative note pertaining to synchronization in [res.on.objects], leaving it ambiguous whether single-threaded code can access a library object during its construction or destruction. For example, there is a reasonable question as to what happens if the deleter supplied to a unique_ptr transitively accesses the unique_ptr itself during unique_ptr's destruction; a straightforward reading suggests that this is permitted, and that the deleter will see the unique_ptr still holding the originally stored pointer, but consensus on the LWG reflector indicates this was not the intent (see discussion beginning with c++std-lib-33362).

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2015-10-27 16:52:45adminsetstatus: ready -> wp
2015-05-05 19:13:23adminsetmessages: + msg7353
2015-05-05 19:13:23adminsetstatus: open -> ready
2013-03-19 17:07:46adminsetmessages: + msg6444
2013-03-18 14:33:00adminsetmessages: + msg6433
2013-03-18 13:02:36adminsetstatus: new -> open
2012-12-18 21:29:43adminsetmessages: + msg6298
2012-12-17 00:00:00admincreate