gcc-4.1 doesn't pack structures with 'char' fields, but does for 'short' or 'int' fields
Package: gcc
Version: 4:4.1.1-1
Severity: important
The following code:
typedef struct {
char a : 3;
char b : 4;
char c : 4;
char d : 4;
char e : 1;
} __attribute__ ((packed)) Bits ;
doesn't compile the same with gcc-4.0.3 and gcc-4.1.2, and may introduce big
runtime errors on optimized softs.
Compiles fine on dapper: gcc (GCC) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
Fails on edgy: gcc (GCC) 4.1.2 20060613 (prerelease) (Ubuntu
4.1.1-2ubuntu3)
If I replace 'char' with 'short', or 'int', it works well even on 4.1.2
.
It is a HARD BUG since gcc compiles without error, but with different
result (that will be seen at runtime...).
See the following full testcase (and the results on dapper AND edgy
after ):
>>>>>>>>>>>>>>>>>>>>>>>
#include <stdio.h>
/*
This testcase shows a strange result when compiling with gcc-4.1:
The 'Bits' structure has 16 bits, I want them to be packed.
In gcc-4.0, it stands into 2 bytes, all bits packed, expected result.
In gcc-4.1, it goes into 3 bytes, with a hole!
Fred Marmond, fmdp@free.fr
*/
#define FieldType char
/* but no problem if the struct is composed of 'short', or 'int', ... */
typedef struct {
FieldType a : 3;
FieldType b : 4;
FieldType c : 4;
FieldType d : 4;
FieldType e : 1;
} __attribute__ ((packed)) Bits ;
main()
{
/*padd0 and padd1 are used to prevent overflows when clearing the Bits
structure.*/
unsigned long long padd0;
Bits bits;
unsigned long long padd1;
/*hack to clear the bits */
unsigned long long* bitsll=(unsigned long long*)(&bits);
*bitsll=(unsigned long long)0LL;
/*set all fields, in order to see the position of fields inside the
structure */
bits.a=0x7;
bits.b=0xf;
bits.c=0xf;
bits.d=0xf;
bits.e=0x1;
printf("sizeof(Bits)=%li\n",sizeof(Bits));
/*shows the real position of fields into the Bits structure*/
printf("mask=0x%llx\n",*bitsll);
return 0;
}
<<<<<<<<<<<<<<<<<<<<<<<<<
RESULT ON DAPPER (correct):
fred@joe_dapper:/tmp$ gcc gcc_packed_testcase.c -o packedtest_4.0 &&
./packedtest_4.0
sizeof(Bits)=2
mask=0xffff
RESULT ON EDGY (WRONG COMPILATION!!!!):
fred@joe_edgy:/tmp$ gcc gcc_packed_testcase.c -o packedtest_4.1 &&
./packedtest_4.1
sizeof(Bits)=3
mask=0x1ff7f
I saw this problem when compiling something that had an union between a
structure 'packed' and a unsigned long. On gcc-4.1.2, as the structure
'packed' is NOT packed correctly, the structure takes much more place
than the 'raw' unsigned long, and the soft crashed at runtime!
I replaced the 'char' in the structure with 'short', that fixes the
problem for my case, but it's not a solution to patch all potentially
problematics softs of the world! ;)
Debian Release: testing/unstable
APT prefers edgy-updates
APT policy: (500, 'edgy-updates'), (500, 'edgy-security'), (500, 'edgy')
Architecture: amd64 (x86_64)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.15-25-amd64-k8
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Versions of packages gcc depends on:
ii cpp 4:4.1.1-1 The GNU C preprocessor (cpp)
ii gcc-4.1 4.1.1-2ubuntu3 The GNU C compiler
Versions of packages gcc recommends:
ii libc6-dev [libc-dev] 2.4-1ubuntu6 GNU C Library: Development
Librari
-- no debconf information
Reply to: