Live data from Hacker News

The Strict Aliasing Situation Is Pretty Bad

blog.regehr.org

21–30 of 70 posts

Re: The Strict Aliasing Situation Is Pretty Bad

#21
post #8

Earlier quoted context omitted.

> 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?

Yes, I believe it would be. That's a good point, now that you mention it -- I have code that does just that, and I hadn't realized it's probably undefined.

The "effective type" (this is a term defined in the standard) of the char array elements would be "char", whereas the memory returned from malloc() is considered to be an object that initially has no effective type. I don't know of any way to take the char array and "erase" its effective type so that it can be used generically, like the value returned from malloc().

This is a problem!

Re: The Strict Aliasing Situation Is Pretty Bad

#22
post #15

Earlier quoted context omitted.

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, s…

I don't see text that justifies your one-way argument, the bit of 6.2.7.1 that we are talking about says "and vice versa".

Re: The Strict Aliasing Situation Is Pretty Bad

#23
post #22

Earlier quoted context omitted.

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, s…

I don't see text that justifies your one-way argument, the bit of 6.2.7.1 that we are talking about says "and vice versa".

I'm not making a one-way argument. If the underlying object actually is a Derived, you can freely cast between pointer-to-Base and pointer-to-Derived. That is what "and vice versa" means.

But if the object isn't actually a Derived, you can't cast to pointer-to-Derived:

    Derived derived;

    Derived *pDerived = &derived;

    // This is legal because it's equivalent to:
    //   Base *pb = &derived.base;
    //
    // ie. there actually is a Base object there that the
    // pointer is pointing to.
    Base *pBase = (Base*)pDerived;

    // This is legal because pBase points to the initial member
    // of a Derived.  So, suitably converted, it points at the
    // Derived.
    //
    // The key point is that there actually is a Derived object
    // there that we are pointing at.
    pDerived = (Derived*)pBase;

    Base base;

    // This is illegal, because this base object is not actually
    // a part of a larger Derived object, it's just a Base.
    // So we have a pDerived that doesn't actually point at a
    // Derived object -- this is illegal.
    pDerived = (Derived*)&base;

    // Imagine if the above were actually legal -- this would
    // reference unallocated memory!
    pDerived->some_derived_member = 5;

Re: The Strict Aliasing Situation Is Pretty Bad

#25
post #15

Earlier quoted context omitted.

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, s…

Looks like your other comment hit the max reply depth so this will need to finish up, but in any case I don't agree with your reading of the vice versa.

Re: The Strict Aliasing Situation Is Pretty Bad

#26

Earlier quoted context omitted.

> 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?

Yes, I believe it would be. That's a good point, now that you mention it -- I have code that does just that, and I hadn't realized it's probably undefined. The "effective type" (this is a term defined in the standard) of the char array elements would be "char", whereas the memory returned from malloc() is considered to be an object that initially has no effective type. I don't know of any way to take the char array a…

Did you even make sure the memory was aligned?

Non-allocated memory (stack char) cannot be used like that. I'm sure you know alloc(), and malloc() is fast for small sizes.

Re: The Strict Aliasing Situation Is Pretty Bad

#27

Earlier quoted context omitted.

Yes, I believe it would be. That's a good point, now that you mention it -- I have code that does just that, and I hadn't realized it's probably undefined. The "effective type" (this is a term defined in the standard) of the char array elements would be "char", whereas the memory returned from malloc() is considered to be an object that initially has no effective type. I don't know of any way to take the char array a…

Did you even make sure the memory was aligned? Non-allocated memory (stack char) cannot be used like that. I'm sure you know alloc(), and malloc() is fast for small sizes.

> Did you even make sure the memory was aligned?

Of course, what do you take me for? :)

> I'm sure you know alloc()

Do you mean alloca? It has a lot of problems, and is generally prohibited at Google.

> and malloc() is fast for small sizes.

Not nearly fast enough for my purposes.

Re: The Strict Aliasing Situation Is Pretty Bad

#28

Earlier quoted context omitted.

Did you even make sure the memory was aligned? Non-allocated memory (stack char) cannot be used like that. I'm sure you know alloc(), and malloc() is fast for small sizes.

> Did you even make sure the memory was aligned? Of course, what do you take me for? :) > I'm sure you know alloc() Do you mean alloca? It has a lot of problems, and is generally prohibited at Google. > and malloc() is fast for small sizes. Not nearly fast enough for my purposes.

> Just making sure. Fix that code will you! :)

> Yes, alloca. (Don't use it.)

> Just make a fast allocator that uses heap instead of the stack. You only need to malloc once and it can be used for any type since like you pointed out, it's effective type can be changed.

Re: The Strict Aliasing Situation Is Pretty Bad

#29
post #25

Earlier quoted context omitted.

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, s…

Looks like your other comment hit the max reply depth so this will need to finish up, but in any case I don't agree with your reading of the vice versa.

It may be that the aliasing rules are also required to fully justify my conclusion (ie. a Base can't have its stored value accessed via a pointer-to-derived due to the aliasing rules). But I have a very high degree of confidence in the conclusion itself. I think that you will find that your compiler implements the behavior I have described.
Post reply on HN