2

In C++, given two structures from a library, one of which inherits from the other as follows:

struct A    
{    
    uint16_t m{2};    
    bool n;    
};    
    
struct B : public A    
{    
    bool o;    
};     

If the library is compiled with gcc as C++11, then sizeof(B) is 4. If m is instead has no member initialization, then the sizeof(B) is 6.

If instead, the library is compiled as C++14 in gcc, the sizeof(B) is 6 in both cases.

This is causing an issue, where a library is C++11 (sees structure as 4 bytes), but an application using the library is C++ 14 (sees structure as 6 bytes) and they disagree on the size of B thus causing memory issues.

Here is a GitHub project demonstrating the issue.

This has been tested on GCC 11 (Ubuntu, Artix), GCC 8/10 (RHEL 7). Clang seems to give consistent sizes between standards, but still shrinks the size of B when a member of A is initialized.

Given this function in the C++11 library:

void printStructInfoFromLib()
{
    std::cout << "Lib size of A: " << sizeof(A) << '\n';
    std::cout << "Lib size of B: " << sizeof(B) << '\n';
}

And this function in the C++14 application

void printStructInfoFromApp()
{
    std::cout << "App size of A: " << sizeof(A) << '\n';
    std::cout << "App size of B: " << sizeof(B) << '\n';
}

Example output:

Lib size of A: 4
Lib size of B: 4

App size of A: 4
App size of B: 6

How can the library and application work together correctly using B? Preferably without pragmas. Also, why does the structure size shrink, when member initialization is used in C++11, but not with C++14 with gcc?

Edit: I updated the GitHub project to show why this is an issue. To restate here:

// function in library
void printInLib(B2 & const b)
{
    std::cout << b.o;
}

// in application side
int main()
{
    B2 b;
    b.o = false;
    std::cout << b.o; // prints 0
    printInLib(b); // prints 127 or whatever uninitialized data was in the padding
}
Wer2
  • 86
  • 4
  • Have you tried using `__attribute__((packed))`? – jxh Apr 13 '22 at 02:46
  • 1
    Class layout is an implementation detail. AFAIK it’s not guaranteed to be stable between compiler versions let alone standard versions. https://stackoverflow.com/questions/5397447/struct-padding-in-c. I would highly recommend NOT packing, FWIW. X86 isn’t too keen on it. – Taekahn Apr 13 '22 at 03:00
  • In this case, it is the same compiler, just different version flags. – Wer2 Apr 13 '22 at 03:09
  • 1
    The standard does not cover interoperability between compiling with different switches, much less combining C++11 and C++14. That is an issue for the compiler to document how much interoperability (if any) they support. – Raymond Chen Apr 13 '22 at 03:41
  • I suggested packing as a way to achieve consistent layout. However, it is unwise to use inheritance as a mechanism to extend data layout, because, as you have encountered, the padding between inherited classes and members can be arbitrary. If possible, you should instead define interfaces to access the members of interest, and use some other means to acquire the data from which the members will be formed. – jxh Apr 13 '22 at 04:33
  • https://tio.run/##lY6xasMwFEV3fcUjGSKRZHCGDrZbsKFf0LUg5CfZiMiSiKWhNf71qrLboVkCfdu9l/M46P15QEx7bdFEqaDWbgo3JcYXksKHV1L1kIuIATgXIdx0F4PinFIv8KokY2QmkC9qG4onHmCcL0u1VZ1zBmxFFmibt9eKkEePTiCMHqyS9MIYgwZK8LEzGjcY5uV/fHvP/0puRi4bVSRlXxiFtkAZ/KxTkGWJLgaoa9hN@lOB66EpYbcWa3Y9bdgaDu/2UD2A2nuo/QMtJH1hb8QwpXOGn/F4LIpv – jxh Apr 13 '22 at 04:36
  • See: https://stackoverflow.com/a/25938871/315052 for an example of defining an interface over managed memory. – jxh Apr 13 '22 at 04:50
  • That C++11 and C++14 have different packing behavior is probably fine. But that a member initialization changes the packing behavior can't be right. – ssbssa Apr 13 '22 at 10:33
  • @ssbssa why not? Padding is an implementation detail of the compiler. You’re not supposed to care or rely on the existence of padding bytes. – Taekahn Apr 13 '22 at 13:24
  • This almost looks like a compiler bug. There should be no way for `A` and `B` to be the same size when `B` has an added member. – Mark Ransom Apr 14 '22 at 00:48

0 Answers0