Live data from Hacker News

GCC always assumes aligned pointer accesses

trust-in-soft.com

81–90 of 93 posts

Re: GCC always assumes aligned pointer accesses

#81
post #80

Earlier quoted context omitted.

This line of J.2 only refers to the already cited 6.5.16.1. You keep quoting this clause as if it applied to any of the assignments in the program being discussed. It doesn't. That clause says that in an assignment of the form “lvalue1 = lvalue2;”, there must only be exact overlap or no overlap between lvalue1 and lvalue2. This does not apply to assignments of the form “lvalue = 1;” or “lvalue = 2;” which are the int…

> You keep quoting this clause as if it applied to any of the assignments in the program being discussed. > It doesn't. You keep asserting that 6.5.16.1 is not relevant, as if it makes it so; but it doesn't. It's your opinion; the assertions are not persuasive. void f(void) { char *t = malloc(1 + sizeof(int)); if (!t) abort(); int *fp = (int*)t; int *fq = (int*)(t+1); h(fp, fq); int h(int *p, int *q){ *p = 1; *q = 1;…

Please explain to me why you think it is.

The clause says:

“If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.”

Under “6.5.16.1 Simple assignment”, so this describes a rule about assignment.

Which assignment in the program are you claiming stores in an object a value read from another object that overlaps in any way the storage of the first object?

Re: GCC always assumes aligned pointer accesses

#82

Earlier quoted context omitted.

The C language does not support what you're trying to do. You should use assembly to do this.

C does support this and has for decades. Many device drivers are written in C and do this exact thing.

The claim was:

> It is common to reference memory mapped peripherals by casting an integer to a struct pointer.

If you check the C standard you'll see that C guarantees nothing about what happens when you do this. I work with a compliant C implementation where this would not work.

Re: GCC always assumes aligned pointer accesses

#83
post #73

Earlier quoted context omitted.

The C language does not support what you're trying to do. You should use assembly to do this.

This is actually more subtle than one would think. Say you were trying to talk to three UART registers at 0xA000, 0xA004, and 0xA008. It's legal to access: *(volatile uint32_t *)(0xA000); *(volatile uint32_t *)(0xA004); *(volatile uint32_t *)(0xA008); The struct equivalent of this would be something like: struct UART_Peripheral { volatile uint32_t control; volatile uint32_t txdata; volatile uint32_t rxdata; }; struct…

The C standard doesn't define what happens when you cast an integer to a pointer like that. For example I work with a compliant C implementation where this would not work, because it uses fat pointers.

Re: GCC always assumes aligned pointer accesses

#84

Earlier quoted context omitted.

C does support this and has for decades. Many device drivers are written in C and do this exact thing.

The claim was: > It is common to reference memory mapped peripherals by casting an integer to a struct pointer. If you check the C standard you'll see that C guarantees nothing about what happens when you do this. I work with a compliant C implementation where this would not work.

The fact is that many (most?) implementations do support this. It is implementation specific. If it never worked, you'd never be able to write a device driver using memory mapped IO in C, which is pure lunacy.

Re: GCC always assumes aligned pointer accesses

#85

Earlier quoted context omitted.

The claim was: > It is common to reference memory mapped peripherals by casting an integer to a struct pointer. If you check the C standard you'll see that C guarantees nothing about what happens when you do this. I work with a compliant C implementation where this would not work.

The fact is that many (most?) implementations do support this. It is implementation specific. If it never worked, you'd never be able to write a device driver using memory mapped IO in C, which is pure lunacy.

> The fact is that many (most?) implementations do support this.

Which implementations?

GCC? The compiler used for the Linux kernel? Why do you think that?

https://gcc.gnu.org/onlinedocs/gcc/Arrays-and-pointers-imple... does not clarify what they do in this case. So it's not defined by the language nor the compiler documentation. How do we know what it does?

Do you check the disassembly? What if it compiles one way one day and another the next because something else changed in your code?

If you write C code to do this and compile it with the most common C compiler, and it works, then you're just lucky! Nobody is guaranteeing it will do anything at all!

It's much better to do it in assembly, where you know it's doing what you want.

Re: GCC always assumes aligned pointer accesses

#86

Earlier quoted context omitted.

The fact is that many (most?) implementations do support this. It is implementation specific. If it never worked, you'd never be able to write a device driver using memory mapped IO in C, which is pure lunacy.

> The fact is that many (most?) implementations do support this. Which implementations? GCC? The compiler used for the Linux kernel? Why do you think that? https://gcc.gnu.org/onlinedocs/gcc/Arrays-and-pointers-imple... does not clarify what they do in this case. So it's not defined by the language nor the compiler documentation. How do we know what it does? Do you check the disassembly? What if it compiles one way o…

Casting integers to pointers is very common in embedded development. You can call these tutorials "wrong" but that is the opposite of what I have experienced in over 30 years of C programming.

You can find 100's of these tutorials online. One example: https://developer.arm.com/tools-and-software/embedded/legacy...

Section 6.3.2.3 of the C standard indicates it is implementation defined: "An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation." (See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf )

Re: GCC always assumes aligned pointer accesses

#87

Earlier quoted context omitted.

> The fact is that many (most?) implementations do support this. Which implementations? GCC? The compiler used for the Linux kernel? Why do you think that? https://gcc.gnu.org/onlinedocs/gcc/Arrays-and-pointers-imple... does not clarify what they do in this case. So it's not defined by the language nor the compiler documentation. How do we know what it does? Do you check the disassembly? What if it compiles one way o…

Casting integers to pointers is very common in embedded development. You can call these tutorials "wrong" but that is the opposite of what I have experienced in over 30 years of C programming. You can find 100's of these tutorials online. One example: https://developer.arm.com/tools-and-software/embedded/legacy... Section 6.3.2.3 of the C standard indicates it is implementation defined: "An integer may be converted t…

> You can call these tutorials "wrong"

I don't know who you're quoting there, but it isn't me! I said C "does not support" it. And it doesn't!

> Section 6.3.2.3 of the C standard indicates it is implementation defined

Yes... and how does the implementation tells it defines it?

If you check the GCC documentation you'll find they don't commit to doing anything when you cast an integer to a pointer and then use it. They deliberately leave it undefined themselves. It could do absolutely anything. And not necessarily what you think it should based on existing code and online tutorials.

If I was reviewing your code that did this, and I asked you "how do you know that this will work as you expect", you'd have nothing to stand on to back it up! You'd just be able to say "well everyone assumes it works". That's not good engineering!

I know it's a common pattern to use. But who is supporting that it will work? Not the C language spec. Not the compiler documentation. It's not supported by anyone. Hence, "does not support it".

Make sense now?

Re: GCC always assumes aligned pointer accesses

#88

Earlier quoted context omitted.

Casting integers to pointers is very common in embedded development. You can call these tutorials "wrong" but that is the opposite of what I have experienced in over 30 years of C programming. You can find 100's of these tutorials online. One example: https://developer.arm.com/tools-and-software/embedded/legacy... Section 6.3.2.3 of the C standard indicates it is implementation defined: "An integer may be converted t…

> You can call these tutorials "wrong" I don't know who you're quoting there, but it isn't me! I said C "does not support" it. And it doesn't! > Section 6.3.2.3 of the C standard indicates it is implementation defined Yes... and how does the implementation tells it defines it? If you check the GCC documentation you'll find they don't commit to doing anything when you cast an integer to a pointer and then use it. They…

Nope.

You can look at the ARM example I included to see how one implementation defines it. It that correct or incorrect? It's implementation defined and supported by compiler vendors. Maybe not yours.

If you can't find out if it's supported for your environment, you shouldn't do it. I agree. But to claim you can't do this with C in general is silly. You clearly can.

Re: GCC always assumes aligned pointer accesses

#89

Earlier quoted context omitted.

> You can call these tutorials "wrong" I don't know who you're quoting there, but it isn't me! I said C "does not support" it. And it doesn't! > Section 6.3.2.3 of the C standard indicates it is implementation defined Yes... and how does the implementation tells it defines it? If you check the GCC documentation you'll find they don't commit to doing anything when you cast an integer to a pointer and then use it. They…

Nope. You can look at the ARM example I included to see how one implementation defines it. It that correct or incorrect? It's implementation defined and supported by compiler vendors. Maybe not yours. If you can't find out if it's supported for your environment, you shouldn't do it. I agree. But to claim you can't do this with C in general is silly. You clearly can.

But this whole thread is about GCC.

Re: GCC always assumes aligned pointer accesses

#90
post #78

Earlier quoted context omitted.

Author here! I am not saying or thinking that there is a problem with GCC. I do think that GCC and Clang would be more useful with an option to make them not assume that every pointer is aligned if the target architecture does not impose this, but that's not the same thing as saying there is something wrong with GCC. The message of the post, rather than “something is wrong with GCC”, is, “Beware. You might think that…

Do you know if there is a compiler switch that can insert run-time checks any time it makes assumptions which could be invalid (such as “this random pointer is aligned”) and abort with an error message (or something) when it is not true? I think this would be invaluable for tracking down odd bugs caused by things like this.

I have seen it said in another thread that UBSan detects this.

If you aren't already using all the sanitizers that come with your {CLang, GCC} compiler, you should! They are great!

UBSan detects everything that can be detected without metadata. It would be its job to find this, since this is a simple mask to apply and test at each pointer access.

UBSan cannot detect if memory is initialized or if a pointer is valid, because these questions cannot be answered locally, looking only at the instruction doing the access. You need metadata for this. The sanitizers that maintain the metadata to answer these questions are respectively MSan and ASan. Their heavy instrumentations are incompatible, so you can only use one at a time.

Post reply on HN