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
}