We had a problem today where my code was generating crazy prices. I eventually boiled it down to the fact that my message classes were the wrong size, even though I am packing on one byte and have unit tests in place to ensure this doesn't ever happen. (Turns out the unit tests were not run under Windows, but that's another problem.)
I've got a traits class template, which is empty except for some static const
s and enum
s, and an implementation of a noncopyable
class which is empty.
When I derive a class from both of the above, the resulting class is padded out by 1 byte, but only under Windows, and only if I derive from both classes. If I derive from one or the other, the class is not padded out.
I realize I am in platform-specific territory here with the #pragma
, but it seems odd to me that only during multiple public inheritance does this not do what I was expecting it to do.
The question is: Why does MSVC pad out the class by 1 byte in the case of multiple public inheritance of empty classes?
Here is an SSCCE that issustrates the problem:
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
#pragma pack (1)
template <size_t ExpectedSize>
class Traits
{
public:
static const size_t mExpSize = ExpectedSize;
};
class noncopyable
{
public:
noncopyable() {};
~noncopyable() {};
private:
noncopyable& operator= (const noncopyable&);
noncopyable (const noncopyable&);
};
class NotEmpty1
{
public:
char mBuf [33];
};
class NotEmpty2
:
public Traits <33>
{
public:
char mBuf [33];
};
class NotEmpty3
:
public noncopyable
{
public:
char mBuf [33];
};
class NotEmpty4
:
public Traits <33>,
public noncopyable
{
public:
char mBuf[33];
};
int main()
{
cout << "Case 1: " << sizeof (NotEmpty1) << "\n"
<< "Case 2: " << sizeof (NotEmpty2) << "\n"
<< "Case 3: " << sizeof (NotEmpty3) << "\n"
<< "Case 4: " << sizeof (NotEmpty4) << "\n"
;
}
The idea here is for all the NotEmpty
classes to be exactly 33 bytes. Under linux (using G++ 4.4.6.4) they are:
Case 1: 33
Case 2: 33
Case 3: 33
Case 4: 33
Under Windows (using MSVC 9 and 10) they are not:
Case 1: 33
Case 2: 33
Case 3: 33
Case 4: 34
Edit: When I use:
#pragma pack (show)
In a variety pf places, the compiler always says:
1>main.cpp(57): warning C4810: value of pragma pack(show) == 1
Edit: Showing the offset of mBuf
wrt the beginning of the class using:
cout << "Offset: " << offsetof(NotEmpty4, mBuf) << "\n";
Reveals:
Offset: 1