This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

g++ 2.95.2 calculates wrong size for class


    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;
    }
};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]