$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 4.7.0 20120224 (Fedora MinGW 4.7.0-0.5.20120224.fc16_cross)
I am attaching test case that you can easily see the problem.
$ gcc -m32 test-ps.c
$ ./a.out
size: 12
$ gcc -fpack-struct -m32 test-ps.c
size: 6
$ i686-w64-mingw32-gcc test-ps.c
$ wine ./a-1.exe
size: 12
$ i686-w64-mingw32-gcc -fpack-struct test-ps.c
$ wine ./a.exe
size: 9
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
test case
Last edit: Anonymous 2014-03-23
The gcc 4.7 gcc for mingw has by default -mms-bitfields activated. Which means struct-layout has changed and alignment in struct.
You can force a specific layout by using attribute ms_struct or by attribute gcc_struct.
The difference between those two layouts is in bitfield packing and in alignment of those field members.
For example:
struct {
unsigned long long c : 1;
unsigned int a : 1;
unsigned int b : 1;
}
will be layout differently.
For gcc-layout all bits geting merged together within one bitfield. gcc struct makes no difference in actual type-sizes for bitfields.
For ms-layout c will end in a 8-byte field, and just a and b getting merged together as they have same type-size.
This is to be expected behavior. You might want to try here -mno-ms-bitfields.
Ah, I missed that default-alignment is treated now for ms_struct union/struct-s too.
You can solve the issue also by additing explicit #pragma pack(1) of __attribute__ ((pack(1))).
The cause why it gets aligned to 9 is that. Default alignment of fields is 4 on 32-bit.
So first char a[1]; is placed in 4-bytes, long b also, and the last element has 4 too.
By enabling struct-pack, All fields in structure getting merged.
So char a[1]; has one byte size, long b has 4 byte size, plus char c[1] has 1. But by structure-alignment of 4, structure gets expanded in the last field to 4.
I see that here alignment is one too big ... hmm, maybe an issue indeed.
Work-a-round use explicit #pragma pack(1), if you don't want structure alignment at end.
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Adding -mno-ms-bitfields does fix the issue that I am having. I was expecting 6 and not 8 (or 9). I did not know about the defaults change. Should I report the 9 issue upstream (gcc)?
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
I was too quick to say it is fixed. There seem to be other byte alignment issues. I will continue investigating.
The general issue is that the __attribute__ ((__packed)) applies only to last field of struct. This is the cause for the size of 9. Trick is here '#pragma pack(1)'. By it you get expected sizes. The issue is that this field-alignment gets applied even for struct/union's marked to be packed (or via -fpack-struct option).
The remark of "__attribute__ ((__packed)) applies only to last field of struct" is curious: I never experienced that before in any gcc versions, and if that is a gcc-4.7 thing it is a devastatingly incompatible change. For the record, I just compiled Michael's testcase with gcc45 for win32 and it prints 6 when ran under wine. Same when compiled for x86-linux. Is your remark accurate Kai?
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
My last comment was a false alarm. Adding "-mno-ms-bitfields" solves all my issues. I use software that heavily relies on bitfields and packed structs (yes, it is very old).
I agree with sezero, even if I am an outside nobody. This is a drastic change in defaults.
Perhaps this "bug" needs to be changed to an "enhancement" to change the defaults back to pre-4.7 values to prevent further problems with other projects.
I run into this as well and I don't think the change is correct. I get now _different_ results from compiling with Microsoft Compiler and packing when using -m-ms-bitfields while I get _identical_ results when compiling with -mno-ms-bitfields. And when __attribute__ ((__packed)) applies only to last field of struct then m[no]-ms-bitfields shouldn't really make a difference in my case:
#include <cstdio>
#if defined(_MSC_VER)
#pragma pack( push, packing )
#pragma pack( 1 )
#endif
struct Header
{
unsigned char IdLength;
unsigned char ColorMapType;
unsigned char ImageType;
unsigned char FirstEntryIndex[2];
unsigned short ColorMapLength;
unsigned char ColorMapEntrySize;
unsigned char XOrigin[2];
unsigned char YOrigin[2];
unsigned short ImageWidth;
}
#if defined(__GNUC__)
__attribute__((packed))
#endif
;
#if defined(_MSC_VER)
#pragma pack( pop, packing )
#endif
int main ()
{
printf("sizeof(Header): %d\n", sizeof(Header));
return 0;
}
But my results for size are:
With VS 2010 (32 bit as well as 64-bit): 14
Compiled with gcc 4.7 and -mno-ms-bitfields: 14
gcc 4.7 and new default (or with -mms-bitfields explicitly): 16
So gcc 4.7 is now incompatible with MS compiler as well as with gcc 4.6 as far as I can see.