InderlockIncrement und 32 Bit-Grenze



  • Hallo alle,

    Ich studiere gerade die MSDN zum Thema InterlockedIncrement/-decrement und finde da:

    The variable pointed to by the Addend parameter must be aligned on a 32-bit boundary; otherwise, this function will fail on multiprocessor x86 systems....

    Das macht mich stutzig - schließlich sind Multiprozessor-Systeme in naher Zukunft Allerwelts-Computer. Meine Frage an euch: Welche Maßnahmen muss ich ergreifen, um hier sicher zu gehen? Wie kriege ich also eine Variable auf eine "32-bit boundary" aligned, so dass die Interlocked-Funktionen garantiert klappen? Was müsste ich also z.B. bei folgendem Code noch ändern:

    class Count {
    public:
        // ....
        bool inc() { return InterlockedIncrement(&var) != 0; }
        bool dec() { return InterlockedDecrement(&var) == 0; }
        // ....
    private:
        long var;
    };
    

    (Zu blöde, dass ich's nicht testen kann, aber mein Rechner hat halt nur einen Prozessor 😞 )

    Danke für euer Interesse,
    Stefan.



  • Ein normales Win32-Programm hat DWORD/long/int Variablen immer an einer 32-Bit Boundary ausgerichtet. Das liegt daran, das das "#pragma pack" auf 8 gestellt ist...
    (und ja, ich bin mir bewusst, das packing und alignment zwei verschiedene Dinge sind).
    Siehe auch:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vcconwindowsdataalignmentonipfx86x86-64.asp

    Das Folgende Beispiel zeigt dies:

    #include <windows.h>
    #include <tchar.h>
    #pragma pack(show)
    class Foo
    {
    public:
      char a;
      DWORD b;
      char c;
      char d;
      int e;
    };
    
    int _tmain()
    {
      Foo *f = new Foo();
      _tprintf(_T("0x%p\n0x%p\n0x%p\n0x%p\n0x%p\n"), &(f->a), &(f->b), &(f->c), &(f->d), &(f->e));
    }
    

    Ergebnis

    0x00336D70
    0x00336D74
    0x00336D78
    0x00336D79
    0x00336D7C
    

    Also das "b" und "e" sind jeweils an einer 32-Bit Boundary ausgerichtet...
    Ganz anders sieht es natürlich aus, wenn Du ein "pragma pack" verwendet hast:

    #pragma pack(2)
    
    0x00336D70
    0x00336D72
    0x00336D76
    0x00336D77
    0x00336D78
    

    Unabhängig vom Packing kannst Du es dann noch mit __declspec(align(4)) anpassen:

    #include <windows.h>
    #include <tchar.h>
    
    #pragma pack(1)
    class Foo
    {
    public:
      char a;
      __declspec(align(4)) DWORD b;
      char c;
      char d;
      __declspec(align(4)) int e;
    };
    
    int _tmain()
    {
      Foo *f = new Foo();
      _tprintf(_T("0x%p\n0x%p\n0x%p\n0x%p\n0x%p\n"), &(f->a), &(f->b), &(f->c), &(f->d), &(f->e));
    }
    
    0x00336D70
    0x00336D74
    0x00336D78
    0x00336D79
    0x00336D7C
    


  • Danke, Jochen! Das ist genau das, was ich brauche.

    Stefan.



  • Jo, und ein "new DWORD()" ist unter Windows auch immer auf einer passenden Adresse.


Anmelden zum Antworten