Speicherabbilder
-
1. Die Win-API beinhaltet ja viele Handles, die allerdings nur einen Wert (int unused) beinhaltet. Dies ist bei allen Handles (bis auf HANDLE, welches nur ein Zeiger auf void ist) der Fall. Und da ich bezweifle, dass in diesem Wert alle Informationen, die man braucht, gesichert sind, sind die eigentlichen Informationen wohl nicht in dem Wert, sondern in nachfolgenden Bytes gesichert. Meine Frage: Stimmt das? Obwohl die Handles in der API nur 4 Bytes groß sind, sind reelle Objekte sehr viel größer, oder?
2. Ich habe ein Problem mit dem Speicherbild von unions (32-Bit-Prozessor):
union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }DUMMYSTRUCTNAME; struct { DWORD LowPart; LONG HighPart; }u; LONGLONG QuadPart; };
struct _SYSTEM_INFO { union{ DWORD dwOemId; // Obsolete field...do not use struct { WORD wProcessorArchitecture; WORD wReserved; }DUMMYSTRUCTNAME; }DUMMYUNIONNAME; DWORD dwPageSize; LPVOID lpMinimumApplicationAddress; LPVOID lpMaximumApplicationAddress; DWORD_PTR dwActiveProcessorMask; DWORD dwNumberOfProcessors; DWORD dwProcessorType; DWORD dwAllocationGranularity; WORD wProcessorLevel; WORD wProcessorRevision; };
struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { struct { DWORD Offset; DWORD OffsetHigh; }DUMMYSTRUCTNAME; PVOID Pointer; }DUMMYUNIONNAME; HANDLE hEvent; };
Wie groß sind Objekte dieser Strukturen, wie setzten sich diese zusammen? Das muss ich wissen, weil ich nämlich eine Schnittstelle schreibe, die ... ach, egal, ich muss es nur wissen.
-
Ein Handle ist immer ein Wink für den Anwender: "Die genaue Implementierung geht dich nichts an."
Dafür gibt es eben diverse Funktionen um mit diesen Handles umzugehen. Es wäre auch äußerst unklug sich die Speicheradresse zu besorgen und per Offset Werte direkt manipulieren zu wollen, was heute geht, muss morgen schon nicht mehr klappen.
Zu den Structs/Unions:
Die Größe kannst du doch immer mit sizeof(...) bestimmen, musst aber im Hinterkopf behalten, dass der Compiler ein Padding (Einschieben von zusätzlichen Bytes) durchführen kann und wahrscheinlich auch tun wird.
In Unions ist immer nur ein Feld/Wert belegt und führt sehr häufig zu Problemen. Der Compiler kann nicht wissen, welches Feld gerade benutzt wird. Eine Union darf somit auch keine Elemente mit Kon/Destruktoren haben.
-
Vicious Falcon schrieb:
Ein Handle ist immer ein Wink für den Anwender: "Die genaue Implementierung geht dich nichts an."
Dafür gibt es eben diverse Funktionen um mit diesen Handles umzugehen. Es wäre auch äußerst unklug sich die Speicheradresse zu besorgen und per Offset Werte direkt manipulieren zu wollen, was heute geht, muss morgen schon nicht mehr klappen.OK, habe ich mir schon gedacht.
Vicious Falcon schrieb:
Zu den Structs/Unions:
Die Größe kannst du doch immer mit sizeof(...) bestimmen, musst aber im Hinterkopf behalten, dass der Compiler ein Padding (Einschieben von zusätzlichen Bytes) durchführen kann und wahrscheinlich auch tun wird.1. Mit dem sizeof-Operator kann ich aber nicht herausfinden, wie groß jedes einzelne Element ist.
2. Ich brauche ein genaues Speicherabbild, wie es hinterher im Assemblercode steht, sonst gibt es hinter Access Violations, dass ich meinen Namen vergesse.Vicious Falcon schrieb:
In Unions ist immer nur ein Feld/Wert belegt und führt sehr häufig zu Problemen. Der Compiler kann nicht wissen, welches Feld gerade benutzt wird. Eine Union darf somit auch keine Elemente mit Kon/Destruktoren haben.
Ich rede gerade nur von unions ohne Konstruktoren und Methoden ...
Wie setzten sich diese geposteten Speicherbilder zusammen, was ist was und wieviel Bytes groß?
-
Ich verstehe jetzt die Frage nicht richtig
union { DWORD dwOemId; // 32 Bit struct { WORD wProcessorArchitecture; // 16 Bit WORD wReserved; // 16 Bit }DUMMYSTRUCTNAME; }DUMMYUNIONNAME;
Es ist reine Interpretationssache.
Entweder du nutzt den Wert dwOemId (32 Bit komplett) ODER du nutzt die beiden Words. Der Speicherbereich ist exakt der Gleiche. Daher _müssen_ ja zwangsläufig die Bereiche gleich groß sein. Die obige Union ist noch vertretbar, schlimm ist es, wenn Zeiger und Values vermischt werden (wie geschrieben, der Compiler kann nicht helfen).
Und das mit dem Speicherbereich macht man ja ab und zu auch so:DWORD* p = myPicture.PixelPtr(x,y); // 32 Bit / Pixel RGBQUAD* quad = reinterpret_cast<RGBQUAD*>(p); quad->rgbBlue = 0x80; // (*p) & 0xFF ist jetzt 0x80
Wie du jetzt auf Asm kommst, ist mir schleierhaft. Meinst du damit, einen Wert ins AX-Register zu schieben und diesen dann durch AL und AH zu verändern?
Kann man sich ja praktisch auch als "Union" vorstellenEdit: Okay deine letzte Frage habe ich irgendwie überlesen. Du kannst aber nicht verlangen, dass wir dir jetzt die Größen der Strukturen auflisten. Durch Addition der einzelnen Member kannst du sie doch ausrechnen, mit sizeof() kannst du dir die Größen, wie geschrieben, auch direkt inkl. Padding ausgeben lassen.
Und noch einmal zu einer wirklich problematischen Unionunion NotGood { size_t iValue; // 32 / 64 Bit int* pValue; // 32 / 64 Bit, Win32/Win64 }; void f() { NotGood bad; bad.iValue = 0x30332324; // ein Wert int i = *bad.pValue; // crasht natürlich }
sizeof(NotGood) ist auf dem vor mir stehenden Rechner 4.
-
Vicious Falcon schrieb:
Ich verstehe jetzt die Frage nicht richtig
union { DWORD dwOemId; // 32 Bit struct { WORD wProcessorArchitecture; // 16 Bit WORD wReserved; // 16 Bit }DUMMYSTRUCTNAME; }DUMMYUNIONNAME;
Es ist reine Interpretationssache.
Entweder du nutzt den Wert dwOemId (32 Bit komplett) ODER du nutzt die beiden Words. Der Speicherbereich ist exakt der Gleiche. Daher _müssen_ ja zwangsläufig die Bereiche gleich groß sein. Die obige Union ist noch vertretbar, schlimm ist es, wenn Zeiger und Values vermischt werden (wie geschrieben, der Compiler kann nicht helfen).Vielen Dank, das hilft mir sehr weiter.
Vicious Falcon schrieb:
Wie du jetzt auf Asm kommst, ist mir schleierhaft. Meinst du damit, einen Wert ins AX-Register zu schieben und diesen dann durch AL und AH zu verändern?
Kann man sich ja praktisch auch als "Union" vorstellenVertrau mir einfach, dass ich weiss, was ich tue. Ich benutze für ein Programm einen Dirty-Hack, der auf korrekte Speicherbilder von Win-API-Strukturen angewiesen ist.
Vicious Falcon schrieb:
Edit: Okay deine letzte Frage habe ich irgendwie überlesen. Du kannst aber nicht verlangen, dass wir dir jetzt die Größen der Strukturen auflisten.
Will ich auch gar nicht, ich wollte bloss wissen, wie sich die Strukturen zusammensetzten.
Vicious Falcon schrieb:
Durch Addition der einzelnen Member kannst du sie doch ausrechnen, mit sizeof() kannst du dir die Größen, wie geschrieben, auch direkt inkl. Padding ausgeben lassen.
Und noch einmal zu einer wirklich problematischen Unionunion NotGood { size_t iValue; // 32 / 64 Bit int* pValue; // 32 / 64 Bit, Win32/Win64 }; void f() { NotGood bad; bad.iValue = 0x30332324; // ein Wert int i = *bad.pValue; // crasht natürlich }
sizeof(NotGood) ist auf dem vor mir stehendem Rechner 4.
OK, darauf achte ich. Vielen Dank!
-
Mir ist, mal wieder viel zu spät
, klar geworden, dass du einige Probleme mit den Größen der einzelnen Typen hast.
Hier eine kleine Auflistung für dein 32 Bit Windowschar, unsigned char, BYTE 8 Bit short, uns. short, WORD 16 Bit int, uns. int, DWORD 32 Bit alle Zeiger LPVOID etc 32 Bit size_t hat immer die Größe eines Zeigers __int64 LONGLONG ULL 64 Bit M128 128 Bit
-
Vicious Falcon schrieb:
Mir ist, mal wieder viel zu spät
, klar geworden, dass du einige Probleme mit den Größen der einzelnen Typen hast.
Hier eine kleine Auflistung für dein 32 Bit Windowschar, unsigned char, BYTE 8 Bit short, uns. short, WORD 16 Bit int, uns. int, DWORD 32 Bit alle Zeiger LPVOID etc 32 Bit size_t hat immer die Größe eines Zeigers __int64 LONGLONG ULL 64 Bit M128 128 Bit
Keine Sorge, das System, das ich verwende, hat IMMER 32 Bit. Sowohl das Speicherabbild als auch die Anwendung. Daher brauche ich mir deswegen keine Sorgen zu machen.
Nein, tatsächlich macht mir etwas anderes Kopfzerbrechen. Wie du bereits gesagt hast, kann der Compiler Optimierungen an den Speicherbildern vornehmen, um die Laufzeit zu verringern (ich habe gehört, dass das Betriebssystem für einen Zugriff auf eine nicht optimierte Struktur viel länger braucht).
Jetzt habe ich hier folgende Klasse:
struct Example { WORD A; //2 Byte ... DWORD B;//... und noch einmal vier. Um auf gesunde 8 Byte zu kommen, muss man noch 2 Bytes drauflegen ... }; ... aber wo? Bereits NACH A (damit B auf das vierte Offset kommt)? Oder viel eher NACH B, weil nur die Schnittstelle sauber bleiben muss, nicht aber die Klasse an sich?
-
Der aus dem Westen ... schrieb:
Jetzt habe ich hier folgende Klasse:
struct Example { WORD A; //2 Byte ... DWORD B;//... und noch einmal vier. Um auf gesunde 8 Byte zu kommen, muss man noch 2 Bytes drauflegen ... }; ... aber wo? Bereits NACH A (damit B auf das vierte Offset kommt)? Oder viel eher NACH B, weil nur die Schnittstelle sauber bleiben muss, nicht aber die Klasse an sich?
Hier musst Du gar nichts drauf packen. B ist alligned auf 4 Bytes. Hinter A sind 2 Bytes Platz, wenn Du kein anders Pack angibst.
Lies doch:
http://msdn.microsoft.com/en-us/library/2e70t5y1(VS.80).aspx
-
Martin Richter schrieb:
Der aus dem Westen ... schrieb:
Jetzt habe ich hier folgende Klasse:
struct Example { WORD A; //2 Byte ... DWORD B;//... und noch einmal vier. Um auf gesunde 8 Byte zu kommen, muss man noch 2 Bytes drauflegen ... }; ... aber wo? Bereits NACH A (damit B auf das vierte Offset kommt)? Oder viel eher NACH B, weil nur die Schnittstelle sauber bleiben muss, nicht aber die Klasse an sich?
Hier musst Du gar nichts drauf packen. B ist alligned auf 4 Bytes. Hinter A sind 2 Bytes Platz, wenn Du kein anders Pack angibst.
Lies doch:
http://msdn.microsoft.com/en-us/library/2e70t5y1(VS.80).aspxVerzeihung, ich habe mich wohl nicht ganz klar ausgedrückt. Ich schreibe nicht in C oder in C++, sondern ich versuche, die Schnittstellen nachzubilden. Mein Fehler.
Aber danke für die Hilfe.