C++ Logo

std-proposals

Advanced search

Re: Allowing access to object representations

From: language.lawyer_at <language.lawyer_at_[hidden]>
Date: Tue, 20 Aug 2019 01:11:34 +0300
On 20/08/2019 00:37, Brian Bi wrote:
> On Mon, Aug 19, 2019 at 4:20 PM language.lawyer--- via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>>> The creation of an object of type T would end the lifetime of the array
>>>> elements, so accessing them would be UB.
>>>>
>>>
>>> An array of unsigned char or std::byte can have an object of some other
>>> type nested within it, so the array's lifetime is not ended.
>>
>> Right, but I wrote that the lifetimes of the array *elements* would end.
>> There is no "nested within" relation between the elements and an object
>> which is placed over them.
>>
>
> [intro.object]/3
> If a complete object is created ([expr.new]
> <http://eel.is/c++draft/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] <http://eel.is/c++draft/cstddef.syn>), that array *provides
> storage* <http://eel.is/c++draft/basic.memobj#def:provides_storage> for the
> created object if: ...
>
> [intro.object]/4
> An object a is *nested within*
> <http://eel.is/c++draft/basic.memobj#def:nested_within> another object b if:
> *...* or b provides storage for a, or ...
>
>
> [basic.life]/1
> The lifetime of an object o of type T ends when: ... the storage which the
> object occupies is released, or is reused by an object that is not nested
> within o ([intro.object] <http://eel.is/c++draft/basic.memobj#intro.object>)
> . <http://eel.is/c++draft/basic.memobj#basic.life-1.sentence-4>

Again: the lifetime of the array won't end, but the lifetime of its *elements*, covered by a newly created object, will.
If, say, an `int` object `i` is created at the beginning of an `unsigned char` array `a`, which one nested within the other: `i` or `a[0]`?
Neither is.

>>>> This just shows that the access to object representations do not fit
>> well
>>>> into the current model of the C++ abstract machine.
>>>>
>>>
>>> Indeed. On one hand, one could conclude that people who want to access
>>> object representations should just suck it up. On the other hand, one
>> could
>>> observe that the current C++ memory and object model results in a lot of
>>> pre-C++17 code being broken, and conclude that it should be revised.
>>>
>>> Besides, even if you think that no one should ever try to access object
>>> representations of anything much more complicated than a struct with a
>>> bunch of ints in it, do you think it is reasonable to limit typical usage
>>> of offsetof to such types as well? If I have a pointer to a member of
>> some
>>> class that is standard-layout but not implicit-lifetime, should there not
>>> be a way for me to get a pointer to the enclosing class using pointer
>>> arithmetic? Are you comfortable with letting all the existing code of
>> this
>>> form, written before C++17, continue to be broken? What did we gain from
>>> the C++17 changes that was so beneficial that it justified *silently
>>> breaking* said code? What about the fact that the migration effort for
>> such
>>> code can be significant (given, as I've pointed out, the inadequacies of
>>> the proposed std::bless solution)?
>>
>> Isn't offsetof usually used in some low-level code which typically also
>> breaks the strict aliasing rule?
>> There are compiler flags making the later behavior defined.
>> It is not forbidden for implementations to define behavior which the
>> standard does not define.
>>
>
> I don't see why that is necessarily the case. It could, for example, be
> used to allow a user to remove an object from a node-based container given
> a pointer to the object. There's no reason why such code should have to
> depend on special flags to make strict aliasing violations well-defined.
> Oh, sure, you can rewrite the container so that its API is based on
> iterators instead, to avoid this problem---and, of course, you'll also have
> to rewrite ALL the code that uses it. As I said, the migration effort is
> "significant".

I do not think that a lot of developers started to rewrite their code because its behavior became undefined in C++17.
(I'd say it always was undefined)

>>>>>> I do not think that this is a good way.
>>>>>>
>>>>>
>>>>> What problem did this cause when it was effectively the status quo in
>>>>> C++14, that is so serious that we should not attempt to codify it in
>>>> C++23
>>>>> or some future version of the standard?
>>>>
>>>> I do not think calling bytes of memory "objects" is a good status quo.
>>>>
>>>
>>> Is that really your only objection? Presumably, it would be possible to
>>> word the changes to the standard in a way that would avoid this. The
>> point
>>> is that existing code relies on being able to do pointer arithmetic on
>>> memory that various types of objects occupy *as though* an array of
>> unsigned
>>> char objects existed there. We don't have to say that there are actual
>>> objects. Given the way pointers work in C++17, I think this would
>> require a
>>> lot of wording, but I think I've already stated enough times how the
>>> alternative of doing nothing leaves a lot of code broken.
>>
>> I don't know the solution for this problem :/
>>
>
> I don't know the solution either, but I felt it was important to point out
> how "just use std::bless" is not a solution.
> It's good that we're at least talking about the OP's proposal (although I
> can't access it right now... what happened to the github link?)

The current version is https://github.com/18/accessing-object-representations/blob/master/P1839R1.md, the original paper was renamed to ...R0.md

Received on 2019-08-19 17:13:39