Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unspecified Implicit Object Creation

Since P0593 Implicit creation of objects for low-level object manipulation has been accepted, objects may now be created implicitly in C++20.

Specifically the wording introduced by the proposal allows certain operations (such as std::malloc) to automatically create and start the lifetime of objects of certain types, so-called implicit-lifetime types, if introduction of such objects would cause a program with otherwise undefined behavior to have defined behavior. See [intro.object]/10.

The draft now further states that if there are multiple sets of such objects that could be created implicitly to give the program defined behavior, it is unspecified which of these sets is created. (The relevant sentence does not seem to be present in the last proposal revision that I could access, R5, but is in the draft commit.)

Is there actually a program for which this choice of implicitly created object set is observable? In other words, is there a program with defined, but unspecified, behavior through this new rule, such that it is possible to infer from the output which sets of types of implicit objects (out of more than one possible one) were created?

Or was this sentence merely meant to clarify the program execution on the abstract machine (without observable impact)?

like image 980
walnut Avatar asked Mar 10 '20 22:03

walnut


1 Answers

Let's take the example in the standard and change it a little bit:

#include <cstdlib>
struct X { int a, b; };
X *make_x() {
  // The call to std::malloc implicitly creates an object of type X
  // and its subobjects a and b, and returns a pointer to that X object
  // (or an object that is pointer-interconvertible ([basic.compound]) with it),
  // in order to give the subsequent class member access operations
  // defined behavior.
  X *p = (X*)std::malloc(sizeof(struct X) * 2); // me: added the *2
  p->a = 1;
  p->b = 2;
  return p;
}

Previously, there was only one set of valid objects that could be created implicitly in that storage - it had to be exactly one X. But now, we have storage for two Xs, but only write to one of them, and nothing in this program ever touches the rest of the bytes. So there are many different sets of objects that could be implicitly created - maybe two Xs, maybe an X and two ints, maybe an X and eight chars, ...

It's not observable which set is created, because if there were any actual observations, that would reduce the possibilities to only those sets which were valid. If we did something like p[1]->a = 3 then the universe of possibilities collapses down to just the one with two Xs.

In other words, multiple sets of implicitly-created-objects are possibly only when there aren't enough observations in the program to distinguish their validity. If there were a way to distinguish, then by definition, they wouldn't all be valid.

like image 191
Barry Avatar answered Nov 05 '22 06:11

Barry