Live data from Hacker News

The Strict Aliasing Situation Is Pretty Bad

blog.regehr.org

11–20 of 70 posts

Re: The Strict Aliasing Situation Is Pretty Bad

#11
post #3

I thought this article was unnecessarily dire. One section claims "Physical Subtyping is Broken", where "physical subtyping" is defined as "the struct-based implementation of inheritance in C." I assume this means the typical pattern of: typedef struct { int base_member_1; int base_member_2; } Base; typedef struct { Base base; int derived_member 1; } Derived; The article claims physical subtyping is broken because ca…

Josh, what's your opinion about this situation?

https://goo.gl/3hz0em

Re: The Strict Aliasing Situation Is Pretty Bad

#12
post #11
post #3

I thought this article was unnecessarily dire. One section claims "Physical Subtyping is Broken", where "physical subtyping" is defined as "the struct-based implementation of inheritance in C." I assume this means the typical pattern of: typedef struct { int base_member_1; int base_member_2; } Base; typedef struct { Base base; int derived_member 1; } Derived; The article claims physical subtyping is broken because ca…

Josh, what's your opinion about this situation? https://goo.gl/3hz0em

That is undefined behavior for two reasons. You're interpreting an object as an object that has an incompatible type.

It also violates string aliasing because 6.5.7. only works for one way. See my other comment.

Derived can alias Base, but not vice-versa.

Re: The Strict Aliasing Situation Is Pretty Bad

#14
post #11
post #3

I thought this article was unnecessarily dire. One section claims "Physical Subtyping is Broken", where "physical subtyping" is defined as "the struct-based implementation of inheritance in C." I assume this means the typical pattern of: typedef struct { int base_member_1; int base_member_2; } Base; typedef struct { Base base; int derived_member 1; } Derived; The article claims physical subtyping is broken because ca…

Josh, what's your opinion about this situation? https://goo.gl/3hz0em

It's undefined. But the same thing would be undefined in C++, a language that has inheritance built-in: https://goo.gl/shOJi1

You can't downcast to a derived type if the object isn't actually an instance of the derived type. That seems straightforward, no?

Re: The Strict Aliasing Situation Is Pretty Bad

#15
post #11

Earlier quoted context omitted.

Josh, what's your opinion about this situation? https://goo.gl/3hz0em

It's undefined. But the same thing would be undefined in C++, a language that has inheritance built-in: https://goo.gl/shOJi1 You can't downcast to a derived type if the object isn't actually an instance of the derived type. That seems straightforward, no?

It doesn't seem straightforward to me: you're using words like base and derived that aren't in the C standard.

Re: The Strict Aliasing Situation Is Pretty Bad

#16
post #15

Earlier quoted context omitted.

It's undefined. But the same thing would be undefined in C++, a language that has inheritance built-in: https://goo.gl/shOJi1 You can't downcast to a derived type if the object isn't actually an instance of the derived type. That seems straightforward, no?

It doesn't seem straightforward to me: you're using words like base and derived that aren't in the C standard.

If we talk in terms of concepts that exist in the C standard, we would say that you can't cast an object to pointer-to-X unless your pointer actually points to an X.

The reason your example is illegal is that you are casting to pointer-to-"struct derived", but the thing being pointed to is not actually a "struct derived."

The "physical subtyping" pattern works because the C standard says that a pointer to a struct, suitably converted, also points to its first member. So a pointer-to-Derived, converted to a pointer-to-Base, points at Derived's first member. But a pointer-to-Base doesn't point at a Derived unless that object actually is a Derived. So the downcast is only legal if the object actually is a Derived.

Re: The Strict Aliasing Situation Is Pretty Bad

#17
post #9

Earlier quoted context omitted.

If you do this Derived* derived = (Derived*)base; and then use both base and derived, is that not violating aliasing rules?

Pretty sure it's safe! Take this program: typedef struct { int x; } Base; typedef struct { Base base; int y; } Derived; int f(Base* b, Derived* d) { b->x = 0; d->base.x = 1; return b->x; } Notice that if we are accessing the base members of "d", we are still accessing them through a struct of type "Base" (d->base.x). If we compile this with strict aliasing, you can see the output is allowing that the two might alias…

Thanks, this is good to know.

Re: The Strict Aliasing Situation Is Pretty Bad

#18
post #8

Earlier quoted context omitted.

Actually, casts to/from char * are always defined in C (chars are always assumed to alias). The author was talking about "chunking" non-char units.

> Actually, casts to/from char * are always defined in C (chars are always assumed to alias). Not true. The standard says you can access any object's value via the char type, but not the reverse. You can't cast a character array to any type and dereference it. > The author was talking about "chunking" non-char units. Sure, but you can call my copy_8_bytes() function like so legally: int64_t a, b = 0; copy_8_bytes(&a,…

> You can't cast a character array to any type and dereference it.

So making your own malloc backed by a static char array is undefined behavior?

Re: The Strict Aliasing Situation Is Pretty Bad

#20
post #3

I thought this article was unnecessarily dire. One section claims "Physical Subtyping is Broken", where "physical subtyping" is defined as "the struct-based implementation of inheritance in C." I assume this means the typical pattern of: typedef struct { int base_member_1; int base_member_2; } Base; typedef struct { Base base; int derived_member 1; } Derived; The article claims physical subtyping is broken because ca…

I'm with you. I wrote the code that breaks this stuff in gcc (and the implementation of struct-sensitive pointer analysis).

It explicitly and deliberately follows the first member rule, as it should :)

In C++, this is covered by 6.5/7, and allowed because it's a type compatible with the effective type of the object (in a standard layout class, a pointer to the a structure object points to the initial member)

Post reply on HN