|
Boost : |
Subject: [boost] [Endian] Unaligned fields in packed structs
From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2011-09-06 19:48:22
Dear All,
One of my all-time worst bugs was due to calling htonl() on an
unaligned field in a packed struct. It worked in debug mode but not in
production code, and there were no compiler warnings about the broken
alignment requirement. So I thought I'd try this:
inline void inplace_byteswap(uint32_t& val)
{
val = (val>>24)
| ((val>>8) & 0x0000ff00)
| ((val<<8) & 0x00ff0000)
| (val<<24);
}
struct S {
uint16_t a;
uint32_t b;
} __attribute__ ((packed));
int main()
{
S s;
s.b = 0x12345678;
byteswap(s.b);
}
This fails to compile: "error: cannot bind packed field âs.S::bâ to
âuint32_t& {aka unsigned int&}â". So it's good that it doesn't just
fail unpredictably at runtime like my old nightmare, but it's not
ideal. If instead I write:
inline uint32_t byteswap(uint32_t val)
{
return (val>>24)
| ((val>>8) & 0x0000ff00)
| ((val<<8) & 0x00ff0000)
| (val<<24);
}
...
s.b = byteswap(s.b);
...
then of course it does work; the unaligned accesses don't "escape" from
where the compiler knows about them and can apply fixups.
Anyway, before I tried this I was already wondering about the choice of
function signatures:
void endian::reorder(T&); // in-place byteswap
void endian::reorder(T src, T& dest); // out-of-place byteswap
What is the rationale (or precedent) for these and not
T endian::reorder(T);
?
If sin(theta) returns its result, why shouldn't reorder(val) do so too?
Regards, Phil.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk