Menu

#2005 i686-pc-mingw32-gcc-4.7.3 sizeof() operator returns incorrect value

OTHER
doc
nobody
gcc (462)
Support
none
Behaves_as_Documented
False
2013-09-21
2013-07-19
JC
No

The sizeof() a packed structure is returning a result different from the additive size of the individual elements of the structure.

The size of the packed structure should be 16 bytes, but sizeof() is returning 17. This has worked correctly under every version of mingw-gcc up until 4.7.3.

Please see the attached file.

$ i686-pc-mingw32-gcc-4.7.3.exe -v
Using built-in specs.
COLLECT_GCC=i686-pc-mingw32-gcc-4.7.3
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-mingw32/4.7.3/lto-wrapper.exe
Target: i686-pc-mingw32
Configured with: /usr/src/packages/mingw-gcc/32/mingw-gcc-4.7.3-1/src/gcc-4.7.3/configure --srcdir=/usr/src/packages/mingw-gcc/32/mingw-gcc-4.7.3-1/src/gcc-4.7.3 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --datarootdir=/usr/share --docdir=/usr/share/doc/mingw-gcc -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-mingw32 --without-libiconv-prefix --without-libintl-prefix --with-sysroot=/usr/i686-pc-mingw32/sys-root --with-build-sysroot=/usr/i686-pc-mingw32/sys-root --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --disable-build-poststage1-with-cxx --enable-version-specific-runtime-libs --disable-multilib --enable-decimal-float=bid --disable-werror --enable-lto
Thread model: win32
gcc version 4.7.3 (GCC)

$ i686-pc-mingw32-ld -v
GNU ld (GNU Binutils) 2.23.1

$ uname -a
CYGWIN_NT-6.1-WOW64 itsrealvm 1.7.21(0.267/5/3) 2013-07-15 12:17 i686 Cygwin

1 Attachments

Related

Issues: #2114

Discussion

  • Earnie Boyd

    Earnie Boyd - 2013-07-19
    • labels: --> gcc
    • status: unread --> open
    • Type: Bug --> Support
     
  • Keith Marshall

    Keith Marshall - 2013-07-19

    GCC 4.7.3 isn't ours. Shouldn't OP be advised to file his bug report with the actual provider of his compiler?

     
    • Earnie Boyd

      Earnie Boyd - 2013-07-19

      I was testing it with my local builds of 4.8.1 before blowing back to Cygwin. The bug must be in GCC or binutils.

       
  • JC

    JC - 2013-07-19

    OP (me) would be happy to, but I was under the impression that since it's the mingw version of GCC, that would be this group? Whom would you suggest? Cygwin or GCC?

     
    • Earnie Boyd

      Earnie Boyd - 2013-07-19

      We do not provide Cygwin with binaries particularly unless one of the other maintainers just do it to be nice. However, this continues in 4.8.1, which is what I've been building natively.

       
  • Earnie Boyd

    Earnie Boyd - 2013-07-19

    You'll probably need to bring this to the attention of the GCC or perhaps binutils maintainers. I found that -fpack-struct=1 gives 16, any other value gives 17.

     
  • dkl

    dkl - 2013-09-20

    This looks like it's a case of gcc bug 52991:

    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991

    (although, that's assuming this problem here exists since gcc 4.7.0 and not just gcc 4.7.3)

    With the example test.c from the opening post, using offsetof() reveals that the version field starts at byte offset 2 instead of 1 in the structure, meaning there is a padding byte inserted between the tag and version fields, despite the __attribute__((packed)). Apparently the struct has no tail padding, but there is padding between fields; this looks exactly like the mentioned gcc bug.

    A possible work-around is to use __attribute__((gcc_struct, packed)) instead of just __attribute__((packed)), or compiling with -mno-ms-bitfields (perhaps less preferable because it could perhaps affect unrelated structures in system headers), both of which override the implicit (default since gcc 4.7.0) __attribute__((ms_struct)) which seems to be the problem's cause. Doing this removes that padding byte, and gives me the expected sizeof() == 16. (tested with MinGW.org gcc 4.8.1)

     
    • Earnie Boyd

      Earnie Boyd - 2013-09-21

      compiling with -mno-ms-bitfields
      which override the implicit (default since gcc 4.7.0) __attribute__((ms_struct)) which seems to be the problem's cause.

      Grumble. The previous maintainers script used -mms-bitfields in the configure step. I removed that since I didn't think it should be used. I didn't realize that it was the default. I think I like the __attribute__((gcc_struct, packed)) idea the best since it would give the correct result regardless of the compiler. Maybe a patch to the compiler bits, I assume this default must be in a config/i386 file somewhere; we could modify the default.

       
  • Earnie Boyd

    Earnie Boyd - 2013-09-21

    Looking at this more, the sizeof() operation is correct. The user is expecting something that isn't real. The result of 17 is correct for the ms_struct method of packing which should be the default since it makes a more compatible binary between the GCC and MSVC compiler sets. The options as dkls points out are:

    • Use -mno-ms-bitfields for the entire object to be affected.
    • Use __attribute__((gcc_struct, packed)) for a particular structure to be affected.
     
  • Earnie Boyd

    Earnie Boyd - 2013-09-21
    • status: open --> doc
    • Category: Unknown --> Behaves_as_Documented
     
  • JC

    JC - 2013-09-21

    While you may believe it's "correct", breaking Dog knows how much software because structure packing no longer works like it used to is insane.

    While your average desktop application may not care that a packed structure is now a little longer, the number of embedded systems that rely on the behavior to be correct is huge.

    Luckily for me, I have a lot of sanity checks in my code base, because the application that I use this compiler for has to talk to other processor architectures like PICs and AVRs. I know that my packed structure should be of 'X' bytes in size, and what the various offsets should be.

    But to silently decide to start changing how packed structures work... Nope, I think you're 100% wrong here.

     
    • Earnie Boyd

      Earnie Boyd - 2013-09-21

      You'll need to change the minds of the GCC upstream maintainers. But you have options to use if you don't want the ms-bitfields structure packing. You could use a specialized specs file to make -mno-ms-bitfields be the default. It wasn't I who made the decision to make it the default but I do agree with the decision.

       
  • dkl

    dkl - 2013-09-21

    From the discussion on that gcc bug report it seemed to me like (at least one of the) GCC mingw target maintainers agreed that not removing the padding bytes is unintentional behaviour for ms_struct+packed, and even a patch was suggested, though not yet applied.