Live data from Hacker News

A bug story: data alignment on x86

pzemtsov.github.io

1–10 of 111 posts

Re: A bug story: data alignment on x86

#3
Well, that's pretty horrendous. Note that the naive code which just casts the input to uint16_t would work fine. I can't help but wonder if the solution to this might have been better expressed as naive implementation + platform-specific assembly implementation.

After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "right" instructions and just write them yourself?

(Language lawyers: is casting a char* to a uint32_t* actually defined behavior? For unaligned data?)

Re: A bug story: data alignment on x86

#4
post #3

Well, that's pretty horrendous. Note that the naive code which just casts the input to uint16_t would work fine. I can't help but wonder if the solution to this might have been better expressed as naive implementation + platform-specific assembly implementation. After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "rig…

No it is not, the author even cited the rule from C99 himself.

> 6.3.2.3 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

The fist sentence is what is in play over here. If you have undefined behaviour in your program anything can happen.

Re: A bug story: data alignment on x86

#5
post #3

Well, that's pretty horrendous. Note that the naive code which just casts the input to uint16_t would work fine. I can't help but wonder if the solution to this might have been better expressed as naive implementation + platform-specific assembly implementation. After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "rig…

Going off a few answers similar to this one [0], I'd say that it isn't defined behaviour. It'll be specific to your compiler, and its optimisations.

The memcpy solution is what I've seen throughout the industry when you are trying to cast between non-trivial types.

[0] http://stackoverflow.com/a/4318446

Re: A bug story: data alignment on x86

#8
These SSE instructions that operate only on aligned data are a pain. It's not well known that Linux/x86 stack frames must always be 16 byte aligned. GCC uses this knowledge to use the SSE aligned instructions when accessing certain fields on the stack.

Unfortunately a while back the OCaml compiler generated non-aligned stack frames. Which is no problem for pure OCaml code and even saves a little bit of memory. However if the code called out to C, then sometimes and unpredictably (think different call stacks, ASLR) the C code would crash. That was a horrible bug to track down:

https://caml.inria.fr/mantis/view.php?id=5700#c10779

Re: A bug story: data alignment on x86

#9
post #3

Well, that's pretty horrendous. Note that the naive code which just casts the input to uint16_t would work fine. I can't help but wonder if the solution to this might have been better expressed as naive implementation + platform-specific assembly implementation. After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "rig…

After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "right" instructions and just write them yourself?

My thoughts exactly. It's especially true for something like this tiny sum-loop, where amusingly enough the "portable C" and C++ versions are longer than the sequence of Asm instructions itself! All the other typical arguments about maintainability etc. don't apply here either --- IPv4 checksum calculation has been defined and implemented in billions of other devices, and is never going to change.

Although what I think Intel could've done is added an optimised REP ADDSW ;-)

Re: A bug story: data alignment on x86

#10
post #3

Well, that's pretty horrendous. Note that the naive code which just casts the input to uint16_t would work fine. I can't help but wonder if the solution to this might have been better expressed as naive implementation + platform-specific assembly implementation. After all, if you have to understand the underlying instructions executed in order to fix the problem, why not stop trying to make the compiler emit the "rig…

People people still try hard to believe ANSI C is 1:1 to Asm, which is only kind of true when using language extensions.

So then better drop down to Assembly, or if there is no need for compiler portability, intrinsics.

Post reply on HN