This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: gcc 2.95.2 has problems with packing and alignment on AIX4.3(reformatted)
- To: hahn at coffee dot psychology dot mcmaster dot ca,gcc at gcc dot gnu dot org,gcc-bugs at gcc dot gnu dot org
- Subject: Re: gcc 2.95.2 has problems with packing and alignment on AIX4.3(reformatted)
- From: "Jeffrey Dickens" <jdickens at ersi dot com>
- Date: Wed, 10 Nov 1999 10:21:50 -0500
- Cc: DBarndt at ersi dot com, LCardani at ersi dot com
Well, I agree that the size of cd might not equal the size of dc, because as you say the compiler is free to
pad and align things the way it wants.
But... the gcc manual says:
"The 'packed' attribute specifies that a variable or structure field should have the smallest possible
alignment-- one byte for a variable and one bit for a field, unless you specify a larger value with the
'aligned' attribute."
That's pretty unambiguous isn't it ? In this example it clearly isn't doing that.
Stepping back a little, the application here its to translate between an internal and external
representation of some data. For years, through many compiler changes, we've used a packed structure
to make sure that data going into our database is formatted exactly as we intend, allowing cross-
architecture compatibility. How better to do that than use a packed structure ?
If I was going to do this in perl instead of C I'd use the "pack" function. See what I mean ?
Jeff Dickens
Software Tools Engineer
ERS Boxborough (978) 264-2832
>>> Mark Hahn <hahn@coffee.psychology.mcmaster.ca> 11/04 4:16 PM >>>
> One would think that the size of "dc" should equal that of "cd" and that
> the size of "dc_packed" should equal that of "cd_packed". It doesn't.
I'm not sure why you think this is a sensible conclusion: the compiler
is free (by the language standard) to put arbitrary padding in structs,
afaik.
> The real problem for us is that we believe the size of "dc_packed"
> should be 9. In fact our code was depending on it. Is this a bad assumption,
> and if so, exactly why ?
any such code is inherently unportable, which to most competent programmers
means "buggy". still, you might try something like -mno-align-double;
the natural alignment of a struct isn't quite the same concept as whether
it has internal padding or not (packed).
regards, mark hahn.
===
since I can't make the "references" headers work with my mailer, here's the original message in full:
I have retested on the latest compiler and simplified my example program in the hope
of getting some kind soul to help confirm or deny that there is a problem.
A good first step would be to try it on another platform. It's a very short program,
attached.
In the following example, "lc" is a struct containing a long and a char, "cl" is a struct
containing a char and a long, "cd" is a struct containing a char and a double, and
"dc" is a struct containing a double and a char.
The example program just does a sizeof() on each of these 4 variables, as well as
on an "__attributes__ ((packed))" version of the same. Here's how it looks
on one system we have running Gcc 2.8.1:
lc size 8
lc_packed size 5
cl size 8
cl_packed size 5
dc size 12
dc_packed size 9
cd size 12
cd_packed size 9
Now here's how it looks with Gcc 2.95.2 on AIX 4.3:
lc size 8
lc_packed size 5
cl size 8
cl_packed size 5
dc size 16
dc_packed size 16
cd size 12
cd_packed size 9
One would think that the size of "dc" should equal that of "cd" and that
the size of "dc_packed" should equal that of "cd_packed". It doesn't.
The real problem for us is that we believe the size of "dc_packed"
should be 9. In fact our code was depending on it. Is this a bad assumption,
and if so, exactly why ?
Here's the source code:
#include <stdio.h>
struct _cl
{
char c;
long l;
};
struct _lc
{
long l;
char c;
};
struct _cd
{
char c;
double d;
};
struct _dc
{
double d;
char c;
};
struct _cl_packed
{
char c_packed __attribute__ ((packed));
long l_packed __attribute__ ((packed));
};
struct _lc_packed
{
long l_packed __attribute__ ((packed));
char c_packed __attribute__ ((packed));
};
struct _cd_packed
{
char c_packed __attribute__ ((packed));
double d_packed __attribute__ ((packed));
};
struct _dc_packed
{
double d_packed __attribute__ ((packed));
char c_packed __attribute__ ((packed));
};
struct _lc lc;
struct _lc_packed lc_packed;
struct _cl cl;
struct _cl_packed cl_packed;
struct _dc dc;
struct _dc_packed dc_packed;
struct _cd cd;
struct _cd_packed cd_packed;
int main (int argc, char* argv[])
{
printf ("lc size %d\n", sizeof(lc));
printf ("lc_packed size %d\n", sizeof(lc_packed));
printf ("cl size %d\n", sizeof(cl));
printf ("cl_packed size %d\n", sizeof(cl_packed));
printf ("dc size %d\n", sizeof(dc));
printf ("dc_packed size %d\n", sizeof(dc_packed));
printf ("cd size %d\n", sizeof(cd));
printf ("cd_packed size %d\n", sizeof(cd_packed));
exit (0);
}