This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
g++ 2.95.2 calculates wrong size for class
- To: <gcc-bugs at gcc dot gnu dot org>
- Subject: g++ 2.95.2 calculates wrong size for class
- From: "Sean Cavanaugh" <sean at dimensionalrift dot com>
- Date: Fri, 5 May 2000 13:21:47 -0700
I have a class which when including an enum, becomes 4 bytes larger than
it should be. Considering these classes represent network packets and must
be of exact size (especially when compared to Windows or others).
The code is in a project of which I can provide the full working source
for Linux (and theoretically any posix system), and is not very large and
quite easy to setup to compile. I tried to create a trivial repro case, but
those seem to work fine. I am running Linux/Debian woody and gcc/g++
2.95.2. Obviously I'm going to leave the enum in global scope for a while
to work around it.
Here is the code fragment. Moving enum PACKETtypes into the class
causes the sizeof(basePacket) to return 12 instead of 8: As an experiement
I also moved 'pad' to the very end of the class definition, and its offset
was still 4. I tried various alterations of the enum (typedef enum foo {}
blah, etc) to no avail.
enum PACKETtypes
{
VIS_PACKET_NULL,
VIS_PACKET_GOING_DOWN,
VIS_PACKET_WANT_FULL_SYNC,
VIS_PACKET_IS_DONE_PORTAL, // Client to Server done portal packet
VIS_PACKET_IS_SYNC_PORTAL,
VIS_PACKET_IS_SYNC_PORTAL_CLUSTER, // Multiple IS_SYNC_PORTAL packets
embedded in a single packet
VIS_PACKET_IS_LOGIN,
VIS_PACKET_IS_LOGIN_ACK,
VIS_PACKET_IS_LEAFTHREAD,
VIS_PACKET_IS_LEAFTHREAD_ACK,
VIS_PACKET_IS_LEAFTHREAD_NAK,
VIS_PACKET_IS_PING,
VIS_PACKET_IS_PONG
};
class basePacket
{
friend void DumpPacketInfo(void);
protected: // data
UINT32 header;
UINT32 pad;
#if 0
public:
enum PACKETtypes
{
VIS_PACKET_NULL,
VIS_PACKET_GOING_DOWN,
VIS_PACKET_WANT_FULL_SYNC,
VIS_PACKET_IS_DONE_PORTAL, // Client to Server done portal packet
VIS_PACKET_IS_SYNC_PORTAL,
VIS_PACKET_IS_SYNC_PORTAL_CLUSTER, // Multiple IS_SYNC_PORTAL packets
embedded in a single packet
VIS_PACKET_IS_LOGIN,
VIS_PACKET_IS_LOGIN_ACK,
VIS_PACKET_IS_LEAFTHREAD,
VIS_PACKET_IS_LEAFTHREAD_ACK,
VIS_PACKET_IS_LEAFTHREAD_NAK,
VIS_PACKET_IS_PING, // Keepalive for when baseportalvis is running (and
every 30 seconds when leafthread is chunking away for long periods of time,
and no data has been received)
VIS_PACKET_IS_PONG
};
#endif
public: // static methods
static INT getPacketSizeByType(INT type);
static void HandleIncomingPacket(basePacket* packet, NetvisSession*
socket);
static void DroppedClientForPortalIndex(long clientid, long index);
public: // construction
basePacket(UINT8 type)
{
setType(type);
setFiller(0);
INT size = getPacketSizeByType(type);
if (size != VARIABLE_LENGTH_PACKET)
{
setSize((UINT16)size);
}
else
{
size = 0;
}
}
public: // methods
void setType(UINT8 type)
{
UINT8* pHeader = reinterpret_cast<UINT8*>(&header);
pHeader[0] = type;
}
void setFiller(UINT8 filler)
{
UINT8* pHeader = reinterpret_cast<UINT8*>(&header);
pHeader[1] = filler;
}
void setSize(UINT16 size)
{
UINT16* pHeader = reinterpret_cast<UINT16*>(&header);
#ifdef __LITTLE_ENDIAN__
pHeader[1] = size;
#endif
#ifdef __BIG_ENDIAN__
pHeader[1] = Endian::Flip(size);
#endif
}
UINT8 getType() const
const UINT8* pHeader = reinterpret_cast<const UINT8*>(&header);
return pHeader[0];
}
UINT8 getFiller() const
const UINT8* pHeader = reinterpret_cast<const UINT8*>(&header);
return pHeader[1];
}
UINT16 getSize() const
{
const UINT16* pHeader = reinterpret_cast<const UINT16*>(&header);
#ifdef __LITTLE_ENDIAN__
return pHeader[1];
#endif
#ifdef __BIG_ENDIAN__
return Endian::Flip(pHeader[1]);
#endif
}
virtual bool validate() const
int size = getPacketSizeByType(getType());
if (size != 0)
{
if (size == getSize())
{
return true;
}
if (size == VARIABLE_LENGTH_PACKET)
{
return true;
}
}
return false;
}
};