C++ Logo

std-discussion

Advanced search

Re: Hostile implementation of strict total order of pointers

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Mon, 24 Jul 2023 07:00:13 +0200
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

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:00:27