Es Zuweisung einen Zeiger auf ein Block mit Seitenspeicher, das heißt PAGES
Anzahl der Seiten, die C++ - Zuordnungen anstelle von weiteren OS-spezifischen zugewiesenen zugewiesenen Zuordnungsfunktionen verwenden (z. B. POSIX's posix_memalign
or C11's aligned_alloc
).
Zuerst weist es PAGES + 1
Seiten des Speichers zu (die Seiten ausgerichtet sein können oder nicht), dann passt es den resultierenden Zeiger vorwärts an, so dass es auf das erste ausgerichtete Byte in dem Ergebnis zeigt. Wenn Sie eine zusätzliche Seite überladen, weiß sie, dass sie sicher groß genug ist, um PAGES
verwendbare Seiten über diesen Punkt hinaus zu haben. Das Programm muss nur sicher sein, dass es mem
s mem
wenn es fertig ist, nicht memAligned
(Löschen der letzteren würde wahrscheinlich entweder das Programm jetzt abstürzen, später wegen Heap Korruption, oder nur Leckspeicher; es ist undefiniertes Verhalten, so schmilzt Ihren Computer zu Schlacke ist ein legales Verhalten).
Diese letzte Zeile entspricht numerisch dem Aufrunden auf das nächste Vielfache der Seitengröße; es fügt dem Zeiger PAGE_SIZE - 1
hinzu (wenn also der Zeiger bereits Seite ausgerichtet war, befindet er sich immer noch auf derselben Seite, ansonsten wird auf die nächste Seite verschoben), dann werden die unteren Bits der Adresse ausgeblendet (wodurch die Addition in "bereits" rückgängig gemacht wird) page aligned "case, und in allen anderen Fällen wird der Zeiger auf den Anfang der ersten Seite zurückgesetzt, die auf den nicht ausgerichteten Zeiger in mem
folgt.
Die Details: ~
ist bitweise invertieren, so ADDR_MASK
, die wahrscheinlich Byte Seiten so etwas wie 0x00000FFF
für 4096 ist, wird 0xFFFFF000
(alle Bits Spiegeln). Wenn &
ein Wert eingegeben wird, werden nur die in beiden Operanden gesetzten Bits beibehalten. Um Beispiele zu nennen: Für einen 32-Bit-Zeiger gehen wir davon aus, dass new
0xDEADBEEF
angibt und PAGE_SIZE
4096 ist. Das Hinzufügen auf 4095 (0xFFF
) bedeutet, dass wir "0xDEADCEEE" haben. Wir maskieren dann mit 0xFFFFF000
, die die niedrigen Bits beseitigt und uns 0xDEADC000
gibt, die erste Seite ausgerichtete Adresse, die 0xDEADBEEF
folgt. Das Gleiche würde mit jeder nicht von Seiten ausgerichteten Adresse passieren, die von new
zurückgegeben wird.
Wenn der Wert bereits Seite obwohl ausgerichtet ist, sagen wir, 0xDEADB000
und fügte hinzu, auf 4095/0xFFF
bringt uns 0xDEADBFFF
(beachten Sie, wie keine Bits in 0xDEADB
geändert), so dass, wenn wir die ausgerichtete Adresse erhalten Maske, bekommen wir 0xDEADB000
wieder , da wir bereits Seiten ausgerichtet waren. Die Umwandlung in uintptr_t
soll sicherstellen, dass wir die Adresse mit mathematischen Operatoren manipulieren können, und sicherstellen, dass bitweise Invertierung alle Bits füllt, die für die Anpassung eines Zeigers erforderlich sind (wenn sie nicht angemessen dimensioniert ist, können Sie invertieren, dann hochkonvertieren und plötzlich hätten Sie links eine Reihe von Nullen, nicht nur die rechte, und Sie würden damit enden, wichtige Bits im Zeiger abzudecken, so dass es auf einen völlig anderen und falschen Ort zeigt).
TL; DR: Es verschwendet Speicher und Sie wollen keinen solchen Code :) –
@KubaOber: Es gibt einige begrenzte Umstände, in denen Seite ausgerichteten Speicher den Abfall wert ist; Einige Betriebssysteme können Optimierungen durchführen, um Speicherkopien zu reduzieren, wenn Daten in den Seitenspeicher gelesen/geschrieben werden. Wenn es Sie eine Seite des Speichers kostet, um Nullkopie-Datenübertragungen auf einem Hochlast-Webserver zu erhalten, ist es das wert. – ShadowRanger
@ShadowRanger Ich sage nicht, dass Sie Ihren Speicher nicht ausrichten sollten, nur dass Sie es tun sollten, indem Sie explizit nach seitenausgerichtetem Speicher fragen. Immerhin, da "PAGES" "groß" ist, wird der dem "neuen" zugrundeliegende Zuordner das Betriebssystem nach dem Speicher fragen. Sie können das also auch selbst tun und auf diese Weise page-aligned storage erhalten. In vielen oder sogar den meisten Fällen ist 'mem' bereits ausgerichtet und dann könntest du' PAGES' vielleicht erhöhen, wenn es nicht const war, und Verschwendung vermeiden, aber ich denke nicht, dass solche Hacks gefördert werden sollten. –