C++ Logo

std-discussion

Advanced search

Re: Hostile implementation of strict total order of pointers

From: Will Hawkins <hawkinsw_at_[hidden]>
Date: Mon, 24 Jul 2023 01:27:08 -0400
On Mon, Jul 24, 2023 at 1:00 AM Edward Catmur <ecatmur_at_[hidden]> wrote:
>
>
>
> On Mon, Jul 24, 2023, 05:12 Will Hawkins via Std-Discussion <std-discussion_at_[hidden]> wrote:
>>
>> On Sun, Jul 23, 2023 at 12:57 PM Lénárd Szolnoki <cpp_at_[hidden]> wrote:
>> >
>> > On Sun, 2023-07-23 at 01:37 -0400, Will Hawkins via Std-Discussion
>> > wrote:
>> > > On Sat, Jul 22, 2023 at 2:47 PM Brian Bi via Std-Discussion
>> > > <std-discussion_at_[hidden]> wrote:
>> > > >
>> > > >
>> > > >
>> > > > On Sat, Jul 22, 2023 at 2:40 PM Lénárd Szolnoki via Std-Discussion
>> > > > <std-discussion_at_[hidden]> wrote:
>> > > > >
>> > > > > Hi,
>> > > > >
>> > > > > Given these two arrays, each being a complete object:
>> > > > >
>> > > > > int a[2];
>> > > > > int b[2];
>> > > > >
>> > > > > The partial ordering of the addresses (defined by the operator <)
>> > > > > of
>> > > > > the int objects within is:
>> > > > >
>> > > > > 1. &a[0] < &a[1]
>> > > > > 2. &b[0] < &b[1]
>> > > > >
>> > > > > A hostile strict total order that is consistent with this is
>> > > > > &a[0] < &b[0] < &a[1] < &b[1].
>> > > > >
>> > > > > Is there wording that prevents the implementation defined strict
>> > > > > total
>> > > > > order to manifest like this?
>> > > >
>> > > >
>> > > > Not as far as I can tell.
>> > >
>> > > Does the last clause of https://eel.is/c++draft/intro.object#9 have
>> > > anything to say about this situation?
>> > >
>> > > ... otherwise, they have distinct addresses and occupy disjoint bytes
>> > > of storage."
>> >
>> > It doesn't. Just because the addresses are interleaved according to
>> > pointer comparison, it doesn't mean that they are also interleaved
>> > according to contiguity, i.e. pointer arithmetic.
>> >
>> > Consider the following (admittedly hostile) implementation:
>> >
>> > The address space is segmented, the segments are disjoint, complete
>> > objects always fully reside within a single segment.
>> >
>> > The < operator compares pointers based on their offsets only.
>> >
>> > std::less compares pointers by offset first, segment second (this is
>> > the weird and hostile one).
>> >
>> > char a[2]; // placed at segment 1, offset 1
>> > char b[2]; // placed at segment 2, offset 1
>> >
>> > The char elements compare in the following order according to
>> > std::less:
>> >
>> > 1. &a[0] (offset 1, segment 1)
>> > 2. &b[0] (offset 1, segment 2)
>> > 3. &a[1] (offset 2, segment 1)
>> > 4. &b[1] (offset 2, segment 2)
>> >
>> > I don't think the standard rules out such an odd implementation, but I
>> > think it should.
>>
>> It seems like expr.rel.4 (in particular, expr.rel.4.3) explicitly
>> allows this situation:
>>
>> 4 [1]
>> The result of comparing unequal pointers to objects is defined in
>> terms of a partial order consistent with the following rules:
>>
>> (4.1)
>> If two pointers point to different elements of the same array, or to
>> subobjects thereof, the pointer to the element with the higher
>> subscript is required to compare greater.
>> (4.2)
>> If two pointers point to different non-static data members of the same
>> object, or to subobjects of such members, recursively, the pointer to
>> the later declared member is required to compare greater provided
>> neither member is a subobject of zero size and their class is not a
>> union.
>> (4.3)
>> Otherwise, neither pointer is required to compare greater than the other.
>
>
> No, that's just saying that expr.rel is a partial ordering. It becomes extended to strictness for the library at https://eel.is/c++draft/comparisons#general-2

Thank you! I think I am tracking now. OP is describing an order that
results *not* from the built-in < operator, but from
"implementation-defined strict total order." I feel stupid for not
reading their original message more closely. I completely
misunderstood until now. I am terribly sorry!
Will


>
>> Sincerely,
>> Will
>>
>> [1] https://eel.is/c++draft/expr.rel#4
>> >
>> > Cheers,
>> > Lénárd
>> > >
>> > > Sincerely,
>> > > Will
>> > >
>> > > >
>> > > > >
>> > > > >
>> > > > > One problem with this is that std::less is commonly used to check
>> > > > > if a
>> > > > > given pointer points within a range. If such a manifestation is
>> > > > > possible then such usages are incorrect (or at least
>> > > > > theoretically not
>> > > > > portable).
>> > > >
>> > > >
>> > > > I agree that this is something that should be banned. To be
>> > > > specific, `&a[0] < &b[0] < &a[1] < &b[1]` is probably the sort of
>> > > > thing that is supposed to be allowed, because the idea behind `<`
>> > > > not being a total order is to support segmented architectures where
>> > > > e.g. it might only compare the offset part of the address. But
>> > > > `std::less` always has to take into account both the segment and
>> > > > offset, so I can't see any reason why it should be allowed to give
>> > > > this "hostile" order.
>> > > >
>> > > > >
>> > > > >
>> > > > > Cheers,
>> > > > > Lénárd
>> > > > >
>> > > > > P.S. Someone pointed this out to me on the #include <C++>
>> > > > > discord.
>> > > > > --
>> > > > > Std-Discussion mailing list
>> > > > > Std-Discussion_at_[hidden]
>> > > > > https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>> > > >
>> > > >
>> > > >
>> > > > --
>> > > > Brian Bi
>> > > > --
>> > > > Std-Discussion mailing list
>> > > > Std-Discussion_at_[hidden]
>> > > > https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>> >
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2023-07-24 05:27:20