[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: