C++ member initialization changes size of structure with inheritance

Viewed 108

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
}
0 Answers
Related