Skip to content

CWG2719 [intro.object] p3 The provided storage should satisfy the alignment requirement of the created object #294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xmh0511 opened this issue Apr 11, 2023 · 15 comments · Fixed by cplusplus/draft#6328

Comments

@xmh0511
Copy link

xmh0511 commented Apr 11, 2023

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[intro.object] p3 says

If a complete object is created ([expr.new]) in storage associated with another object e of type “array of N unsigned char” or of type “array of N std​::​byte” ([cstddef.syn]), that array provides storage for the created object if:

  • the lifetime of e has begun and not ended, and
  • the storage for the new object fits entirely within e, and
  • there is no array object that satisfies these constraints nested within e.

No bullet in the list explicitly mentions the alignment requirement of the object being created. [basic.life] p1 says

The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and

The array with the element of type unsigned char or std​::​byte has the weakest alignment requirement per [basic.align] p6 and [expr.alignof] p3. That is, the storage provided by the array is not necessary to satisfy the alignment requirement of the object being created.

@frederick-vs-ja
Copy link

[basic.align] p1 seems already sufficient.

I think the intent is that when there's no suffient size after an properly aligned address for a T object in the array, a T object is simply not created at that address. E.g. given object definition unsigned char buf[sizeof(int)]; without alignas, an int object can be created within it only if the array happens to be allocated at an address properly aligned for int.

@xmh0511
Copy link
Author

xmh0511 commented Apr 11, 2023

I think the intent is that when there's no suffient size after an properly aligned address for a T object in the array, a T object is simply not created at that address.

We do not say so. The rule simply states that the array will provide storage for the object if the bullets in the list are met. Even the referenced subclause [expr.new] does not place the requirement.

The new-expression attempts to create an object of the type-id ([dcl.name]) or new-type-id to which it is applied.

@frederick-vs-ja
Copy link

The rule simply states that the array will provide storage for the object if the bullets in the list are met.

This is sufficient. When it's possible to say the storage for the new object, the storage must be properly aligned to be so ([basic.align] p1).

@xmh0511
Copy link
Author

xmh0511 commented Apr 11, 2023

The rule simply states that the array will provide storage for the object if the bullets in the list are met.

This is sufficient. When it's possible to say the storage for the new object, the storage must be properly aligned to be so ([basic.align] p1).

That's insufficient. Whether the lifetime of an object has begun or ended does not mean that the object is created or not. This is implied by [intro.object] p2

If an object is created in storage associated with a member subobject or array element e (which may or may not be within its lifetime)

A member subobject is called an object regardless of whether the object is within its lifetime or not. Moreover, in terms of creating object, we just say

An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).

Creating an object is unconditional as long as it's the case recorded in the rule.

@xmh0511
Copy link
Author

xmh0511 commented Apr 11, 2023

Incidentally, [basic.align] p1 use "may", "can" rather than "shall"

Object types have alignment requirements ([basic.fundamental], [basic.compound]) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated.

The [intro.object] example-1 implies the point

struct A { unsigned char a[32]; };
struct B { unsigned char b[16]; };
A a;
B *b = new (a.a + 8) B;                 // a.a provides storage for *b
int *p = new (b->b + 4) int;            // b->b provides storage for *p
                                        // a.a does not provide storage for *p (directly),
                                        // but *p is nested within a (see below)

b->b does not guarantee the alignment requirement of int, however, the comment says b->b provides storage for *p

@languagelawyer
Copy link

No bullet in the list explicitly mentions the alignment requirement of the object being created

And why it should?

[basic.life] p1 says

So an array will provide storage for an object whose lifetime has never started (or, rather, this should be fixed separately and become UB)

@frederick-vs-ja
Copy link

That's insufficient. Whether the lifetime of an object has begun or ended does not mean that the object is created or not. This is implied by [intro.object] p2

If an object is created in storage associated with a member subobject or array element e (which may or may not be within its lifetime)

A member subobject is called an object regardless of whether the object is within its lifetime or not.

I don't see the relation. The member subobject or array element may be not created before.

There may be gaps in the specification that may allow some operations to create an object without starting lifetime, which needs to be fixed IMO.

@xmh0511
Copy link
Author

xmh0511 commented Apr 11, 2023

@frederick-vs-ja See my last comment, which literally negates your opinion: an object won't be created at the storage that does not satisfy the alignment requirement of the object.

It is indeed created, merely its lifetime never begins.

@frederick-vs-ja
Copy link

frederick-vs-ja commented Apr 11, 2023

It is indeed created, merely its lifetime never begins.

I don't think this can be right. I think [basic.align] p1 imposes a precondition to object creation. How can an object be created at an address where it can't be allocated?

@xmh0511
Copy link
Author

xmh0511 commented Apr 11, 2023

It is indeed created, merely its lifetime never begins.

I don't think this can be right. I think [basic.align] p1 imposes a precondition to object creation. How can an object be created at an address where it can't be allocated?

See #294 (comment), I agree with @languagelawyer here, that is, the object is indeed created.

@frederick-vs-ja
Copy link

See #294 (comment), I agree with @languagelawyer here, that is, the object is indeed created.

So how do you interpret [basic.align] p1 in this case? If we claim that the object is created, then it seems unavoidable to conclude that the object is allocated at some address that violates [basic.align] p1.

@xmh0511
Copy link
Author

xmh0511 commented Apr 12, 2023

See #294 (comment), I agree with @languagelawyer here, that is, the object is indeed created.

So how do you interpret [basic.align] p1 in this case? If we claim that the object is created, then it seems unavoidable to conclude that the object is allocated at some address that violates [basic.align] p1.

As I said in the above comment, the wording uses "may", and "can" modal verbs, which arguably is a suggestion. If the wording implies the intent as you said, it should say:

An object is created at storage if and only if the address of the storage satisfies the alignment requirement imposed by the object type.

Actually, the current wording does not imply this meaning.

@jensmaurer
Copy link
Member

As a side note, the "may" here conveys permission, not possibility, per ISO drafting rules.

In any case, I think we should explicitly say somewhere that it's undefined behavior to attempt to create an object in too-small storage or in misaligned storage. This also covers implicitly created objects, because possibly implicitly-created objects that are too big to fit into the storage won't satisfy the "no UB" rule and thus won't be created to start with.

@frederick-vs-ja
Copy link

As I said in the above comment, the wording uses "may", and "can" modal verbs, which arguably is a suggestion.

Such reading seems contradictory. If the first sentence of [basic.align] p1 can be merely a suggestion, then it's wrong to say "place restrictions".

@jensmaurer
Copy link
Member

CWG2719

@jensmaurer jensmaurer changed the title [intro.object] p3 The provided storage should satisfy the alignment requirement of the created object CWG2719 [intro.object] p3 The provided storage should satisfy the alignment requirement of the created object Apr 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants