none
Datatype Misalignment RRS feed

  • Question

  • Hello:

    Is there any way to determine beforehand if everything I have declared will have the correct datatype alignment?

    For example, While in Debug, I get a program crash with a datatype misallignemt error message when I run this code:

    void CComDataClass::vGetSystemTime( ULONGLONG *pwqSystemTime)
    {
       // Check pointer
       if (pwqSystemTime == NULL) return;

       FILETIME   ftTimeNow;
       SYSTEMTIME stTimeNow;

       // Lock critical code section
       EnterCriticalSection(&m_csSystemTime);

       // Get the current system time
       GetLocalTime(&stTimeNow);
       SystemTimeToFileTime(&stTimeNow, &ftTimeNow);

       // Convert to ULONGLONG
    FAILS HERE ===>   *pwqSystemTime = (((ULONGLONG) ftTimeNow.dwHighDateTime) << 32) + ftTimeNow.dwLowDateTime;

       // Free critical code section
       LeaveCriticalSection(&m_csSystemTime);
    }

    The vGetSystemTime() routine is declared as part of a Class object:

    class CComDataClass {
     public:
        CComDataClass();
        virtual ~CComDataClass();
        BOOL bCommonDataFailed(void);
        .
        .
        .
        void  vGetSystemTime(ULONGLONG *pqwSystemTime);
        .
        .
        .

     private:
        CRITICAL_SECTION m_csCfgData;
        CRITICAL_SECTION m_csSetupCfg;
        .
        .
        .
        CRITICAL_SECTION m_csSystemTime;
        ULONGLONG m_qwHostTime;
        .
        .
        .
        CFG_DATA *m_psSetupCfg;
    };

    The datatype misalignment problem goes away if I change to the following:

        void  vGetSystemTime(ULONGLONG __unaligned *pqwSystemTime);

    By just adding the '__unaligned', the problem goes away.

    But my question is:
        How do I suppose to know I need to add the '__unaligned' statement to my declarations?

    In other words:
        How do I determine if what I declare is going to be datatype misaligned and crash when I run the application?

    How can I look at all the declarations in all of my Class object definitions and determine if any of them are going to be of datatype misaligned?

    Thanks.

    Also, In this same code I am getting other 'datatype misallignemt' error messages BUT by just by moving around some of the 'CRITICAL_SECTION' declarations, the 'datatype misallignemt' error messages no longer occurs.

    I have found a few places that talk about datatype alignment that helps a bit but are rather old.

    http://blog.softwareverify.com/64-bit-porting-gotcha-1-x64-datatype-misalignment/

    http://blogs.msdn.com/b/grantri/archive/2004/07/14/183524.aspx

    https://msdn.microsoft.com/en-us/library/aa290049%28VS.71%29.aspx

    Tuesday, March 3, 2015 5:09 PM

All replies

  • Any casted pointer type can cause a problem (you take the address of field A, size B, then reinterpret the pointer as a pointer to C where sizeof(C) > sizeof(B)). In this case, you have two back-to-back 32-bit values which are then interpreted as a 64-bit value. Since each field type must be aligned on a boundary of the same size (32-bit value must be on a 32-bit boundary, 64-bit on a 64-bit boundary), you can successfully access each 32-bit value separately (the compiler automatically pads the structure) but not the combination as a single 64-bit (since the compiler doesn't know you're going to treat the two values as one).

    You can change your structure declaration to place padding yourself. Because you'll be thinking about alignment you should be able to spot problems and you'll have practice thinking about where boundaries are located.

    You can alternatively change your pointer cast so the bytes of the target will be accessed individually. Since this is a *lot* slower than a single I/O grabbing the whole value, take care to do this only when necessary.

    Finally you can reconstruct your structure so that a union of two 32-bit values and one 64-bit values appear. The compiler will do the right thing allowing you to read the value as two 32-bit values (mystruct.myunion.partA, mystruct.myunion.partB), or one 64-bit value (mystruct.myunion.bothParts).

    Paul T.

    Wednesday, March 4, 2015 4:37 PM