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.aspDas 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 0x00336D7CAlso 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 0x00336D78Unabhä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.