2

I'd like to know when the size of a struct does not equal the combined size of it's members, in other words, when it is padded. gcc has a warning option to do exactly that, -Wpadded.

From https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html: "Warn if padding is included in a structure, either to align an element of the structure or to align the whole structure."

Using this option didn't seem to catch padding where it should've though, so I wrote a simple test to demonstrate my issue:

#include <iostream>
#include <cstdint>

using namespace std;

struct test {
    uint16_t a;
    uint8_t b;
} test;

int main() {
    cout << sizeof(test) << ", " << alignof(test) << std::endl; 

    return 0;
}

compiling this with g++ test.cpp -Wpadded outputs warning: padding struct size to alignment boundary, and running the executable gives 4, 2, exactly as I'd expect. Changing the struct to

struct test {
    uint8_t b;
    uint16_t a;
} test;

and running the resulting executable gives 4, 2, but no warning is given.

Both structs have the same size and alignment, the size of uint8_t is obviously 1 byte, and uint16_t 2, so shouldn't I be getting a warning here? A page talking about various gcc options (https://interrupt.memfault.com/blog/best-and-worst-gcc-clang-compiler-flags) has a test similar to this one, and according to them, a warning is output in both situations.

I also ported the code to C (without the prints)

#include <stdint.h>

struct test {
    uint8_t b;
    uint16_t a;
} test;

int main() {
    return 0;
}

And got the same result.

I'm using gcc 8.1.0 from MinGW-W64.

the4naves
  • 333
  • 2
  • 9
  • 1
    I see warnings for both: https://godbolt.org/z/P1YxKaGGd – aschepler Apr 12 '21 at 01:07
  • 1
    Works as expected here: https://godbolt.org/z/cGd1sKGEb Maybe just a MinGW thing – Retired Ninja Apr 12 '21 at 01:08
  • @RetiredNinja That's odd, it's possible it is just MinGW, but searching 'mingw-w64 "Wpadding"' doesn't come up with anything, I feel like surely someone else would've noticed. – the4naves Apr 12 '21 at 01:11
  • Reinstalling MinGW didn't help, neither did porting the code to C. – the4naves Apr 12 '21 at 01:33
  • Could you paste the exact test program with missing warning, and the command you're using to compile it? – aschepler Apr 12 '21 at 01:37
  • @aschepler The given code is the exact program. Command is `g++ test.cpp -Wpadded` or `gcc ...` on my C port. The C port just takes out the printing, changes to , and takes out anything to do with std. – the4naves Apr 12 '21 at 01:40
  • Forgive the suspicion of user error, but describing the edits made will leave out details the author is blind to, but an actual cut and paste won't. – aschepler Apr 12 '21 at 01:46
  • @aschepler I added the C code to the question. – the4naves Apr 12 '21 at 02:03
  • Yes, still gives me the warning. Strange. – aschepler Apr 12 '21 at 02:46
  • 1
    Try it with [-mno-ms-bitfields](https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mms-bitfields). – ssbssa Apr 12 '21 at 11:02
  • 1
    Can be reproduced on linux with [-mms-bitfields](https://godbolt.org/z/GGzc37vjq). – ssbssa Apr 12 '21 at 15:27
  • 1
    @ssbssa Interesting! Compiling with `-mno-ms-bitfields` does successfully give both warnings. I'll have to read the docs for the option a bit more, but that's something. – the4naves Apr 12 '21 at 18:50
  • With the above option, I also managed to find a question from ~9 years ago (https://stackoverflow.com/questions/11283164/a-bug-in-gcc-implementation-of-bit-fields) that has a similar problem, with a solution being to use the option. It seems msvc's packing behavior is a bit odd, and for compatibility on windows targets, gcc uses msvc's behavior by default. – the4naves Apr 12 '21 at 19:06
  • 1
    But according to the [documentation](https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mms-bitfields), this option should only make a difference for either `packed` structures, or structures containing bit-fields. So I do think this is a bug with `-Wpadded`, since this example doesn't contain any of them. – ssbssa Apr 12 '21 at 19:18
  • @ssbssa I found that odd as well, especially as the C++ example printed the same sizes/alignments for both structs, so you're probably right about it being a problem with the warning. – the4naves Apr 12 '21 at 19:25
  • 1
    I think the changes for [this bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52238) are responsible, since it added a check for `!targetm.ms_bitfield_layout_p (rli->t)` to this variant of the `-Wpadding` option. – ssbssa Apr 12 '21 at 20:34
  • 1
    @ssbssa That seems likely, as the bug was reported for 4.2. Using https://godbolt.org/, I can replicate the issue in all gcc versions 10.3-4.4, but not 4.1. I'll try and open a bug report on the gcc bugzilla. – the4naves Apr 13 '21 at 00:29

1 Answers1

1

Answer is in the comments, but for someone who will just seek answer in "big post":

As @ssbssa suggested:

Try it with -mno-ms-bitfields.

It will work when compiling with both -Wpadded and -mno-ms-bitfields flags active.

zix527
  • 71
  • 1
  • 5
  • Note that although this *will* cause padding to be correctly reported, `-mno-ms-bitfields` may change the way bitfields are packed, which could change the behavior of a program. This is almost certainly a bug in GCC, which has been reported at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100058. – the4naves Nov 12 '22 at 04:00