[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v6 1/4] xen: introduce SYMBOL

>>> On 15.01.19 at 21:03, <Stewart.Hildebrand@xxxxxxxxxxxxxxx> wrote:
> On Tuesday, January 15, 2019 3:21 AM, Jan Beulich wrote:
>> The thing that I don't understand though is how the undefined
>> behavior (if there really is any) goes away: Even if you compare
>> the contents of the variables instead of the original (perhaps
>> casted) pointers, in the end you still compare what C would
>> consider pointers to different objects. It's merely a different
>> way of hiding that fact from C. Undefined behavior would imo
>> go away only if those comparisons/subtractions didn't happen
>> in C anymore. IOW - see my .startof.() / .sizeof.() proposal.
> No, the C standard provides us a guarantee.
> To quote the ISO/IEC 9899 C99 standard regarding the subtract operator:
>> For subtraction, one of the following shall hold:
>> - both operands have arithmetic type;
>> - both operands are pointers to qualified or unqualified versions of
>>   compatible object types; or
>> - the left operand is a pointer to an object type and the right operand
>>   has integer type.
>> If both operands have arithmetic type, the usual arithmetic conversions
>> are performed on them.
>> When an expression that has integer type is added to or subtracted from
>> a pointer ... If both the pointer operand and the result point to
>> elements of the same array object, or one past the last element of the
>> array object, the evaluation shall not produce an overflow; otherwise,
>> the behavior is undefined.
> Here, "arithmetic type" is either integer type or floating point type (but
> NOT pointer type).
> There is similar language for the equality comparison operator that
> Stefano quoted earlier in the thread.
> My interpretation of the standard is:
> Subtract/compare operations where one or both operands are pointer types
> are potentially subject to the "pointers to different objects" issue, and
> the compiler is free to make that determination by any means available.
> Subtract/compare operations where both operands are integer types are well
> defined in the C standard, and, per the C standard, are NOT subject to the
> "pointers to different objects" issue. If the compiler starts to consider
> integer types being "pointers to different objects" then the compiler
> clearly does not adhere to the C standard. The compiler may look through
> *pointer type* casts, but if it started to look through *integer type*
> casts, we would have good reason to complain to the GCC mailing list.

All fine. Yet wasn't it you who suggested that a future, very smart
compiler could "look through" casts and even inline assembly? Of
course subtraction and comparison of arithmetic types is well
defined. The question is whether this also holds for pointers
casted to such types. Let's not forget that in the abstract case,
casting a pointer to an integral type may be lossy, and subtraction
of two such casted values may not represent what you'd expect
it to be.

The best way to demonstrate this are the historic large and huge
memory models on 16-bit x86. Pointers are comprised of a
segment/selector and an offset there. When the former is a
segment (real or vm86 modes), conversion can be done such that
the difference is "meaningful" in our sense. When it's a selector,
otoh, I can't think of a conversion that would allow meaningful
comparison / subtraction. Even worse, two entirely distinct
pointers (different selectors referring to descriptors with
different base addresses) may point at the same object.

Luckily we don't have to consider such obscure environments
(and hence we can make certain implications), but the C standard
has to.

In any event - since intermediate variables merely hide the
casting from the compiler, but they don't remove the casts, the
solution involving casts is better imo, for incurring less overhead.

Since casts, as discussed before, are not meaningfully more
helpful than hiding the origin object from the compiler, retaining
pointer types is (to me) further preferable over the casting to
integer types, not the least because of the general risk involved
with type changing casts (for the last so many years I've been
objecting to unnecessary casts in all of the reviews I've done
for this very reason).

> Just to reiterate, MISRA C says: don't subtract/compare *pointer types*
> pointing to different objects, otherwise it's "undefined behavior" except
> in one irrelevant corner case (I'm paraphrasing since the actual text is
> copyrighted). If the operands are both integer types (not pointer types),
> we don't risk violating the MISRA rules pertaining to pointer types.

I continue to have two problems with this: For one this doesn't
talk about pointers cast to integers. And then the term
"different object" is fuzzy as soon as we're talking about things
coming from outside of C land. And taking into consideration
language extensions (are such inside or outside of C land?) like
weak aliases, things become even more fuzzy. gcc looks to be
prepared for such - just look at the generated code for

extern int ei1, ei2;
int i1 = 1, i2 = 2;
extern int ai1[], ai2[];
int __attribute__((weak)) wi1 = 1;
int __attribute__((weak)) wi2 = 2;

int test1(void) {
        return &ei1 == &ei2;

int test2(void) {
        return ai1 == ai2;

int test3(void) {
        return &i1 == &i2;

int test4(void) {
        return &wi1 == &wi2;

And there are further issues of fuzziness - take for example the
folding of literals. Are two distinct instances of identical (string)
literals one object, or two different ones? I've searched the spec,
but couldn't spot any statement. Yet the "if and only if" in the
wording of the equality operator descriptions requires this to be
well defined.


Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.