Packed structs and C++
Nathan Sidwell
nathan@codesourcery.com
Sat Jul 5 19:29:00 GMT 2003
When we pack a structure, the type of the packed fields does
not become 'attribute((unaligned)) T'. this causes problems with
taking their address and that happens 'invisibly' with passing by
reference. Here is some example code.
struct Foo {
char c;
int i __attribute__((packed));
};
typedef map<int,int> Map_t;
void Foo (Map_t &m, int from, int to)
{
Foo f;
f.i = from;
#if 1
m.insert(map::value_type(f.i, to)); // fails
#else
int t = f.i;
m.insert(map::value_type(t, to)); // works
#endif
m.find (from); // will it be found?
}
why does this happen? Well, map::value_type (f.i, to) calls
pair<int, int>::pair (L const &, R const &);
which implicitly takes the address of f.i, and loses the unalignedness
information. This can lead to bus errors or silently reading the wrong
memory locations.
solution0)
do nothing. I think this is unacceptable. In C, it is more obvious when
you are taking the address of something, in C++ it happens much more
quietly.
solution1)
packed fields have an unaligned type, and that is propagated through
the type system just as cv-qualifiers are. This will also work for
C, and give allow the user to specify when unaligned objects might be
pointed to. Template deduction will probably have to start deducing
attributes -- bleah!
solution2)
packed fields are like bitfields. Thus they cannot have their address
taken and they can bind to 'T const &' parameters by invoking
the copy constructor. If they cannot have their address taken, do
we want offsetof (M, packedField) to work or not?
thoughts?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
The voices in my head said this was stupid too
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
More information about the Gcc
mailing list