Ich habe ein AC-Programm, das so aussieht
Haupt c
#include <stdio.h>
#define SOME_VAR 10
static int heap[SOME_VAR];
int main(void) {
printf("%p", heap);
return 0;
}
und gibt dies aus, wenn ich das kompilierte Programm einige Male ausführe
0x58aa7c49060
0x56555644060
0x2f8d1f8e060
0x92f58280060
0x59551c53060
0xd474ed6e060
0x767c4561060
0xf515aeda060
0xbe62367e060
Warum endet es immer mit 060? Und ist das Array im Heap gespeichert?
Bearbeiten: Ich bin unter Linux und ich habe ASLR auf. Ich habe das Programm mit gcc kompiliert
Antworten:
Die Adressen unterscheiden sich aufgrund von ASLR (Address Space Layout Ramdomization). Auf diese Weise kann die Binärdatei an verschiedenen Stellen im virtuellen Adressraum abgebildet werden.
Die Variable
heap
befindet sich - im Gegensatz zu ihrem Namen - nicht auf dem Heap, sondern auf dembss
. Der Offset im Adressraum ist daher konstant.Seiten werden mit einer Seitengranularität zugeordnet, die auf vielen Plattformen 4096 Byte (hex: 0x1000) beträgt. Dies ist der Grund, warum die letzten drei Hex-Ziffern der Adresse gleich sind.
Wenn Sie dasselbe mit einer Stapelvariablen gemacht haben , kann die Adresse auf einigen Plattformen (nämlich Linux mit aktuellen Kerneln) sogar in den letzten Ziffern variieren, da der Stapel nicht nur an einer anderen Stelle zugeordnet wird, sondern beim Start auch einen zufälligen Versatz erhält.
quelle
heap
wenn sie sich nicht im Heap befindet?060
.Wenn Sie Windows verwenden, liegt der Grund in der PE- Struktur.
Ihre
heap
Variable wird in einem.data
Dateibereich gespeichert und ihre Adresse wird basierend auf dem Beginn dieses Abschnitts berechnet. Jeder Abschnitt wird unabhängig in eine Adresse geladen, aber seine Startadresse ist ein Vielfaches der Seitengröße. Da Sie keine anderen Variablen haben, ist die Adresse wahrscheinlich der Anfang des.data
Abschnitts, sodass die Adresse ein Vielfaches der Blockgröße beträgt.Dies ist beispielsweise die Tabelle der kompilierten Windows-Version Ihres Codes: In diesem
.text
Abschnitt befindet sich Ihr kompilierter Code und.data
enthält Ihreheap
Variable. Wenn Ihr PE in den Speicher geladen wird, werden Abschnitte unter einer anderen Adresse geladen, die von zurückgegeben wirdVirtualAlloc()
und ein Vielfaches der Seitengröße aufweist. Die Adresse jeder Variablen ist jedoch relativ zum Beginn des Abschnitts, der jetzt eine Seitengröße hat. Sie sehen also immer eine feste Zahl auf niedrigeren Ziffern. Da die relative Adresseheap
von Anfang des Abschnitts auf Compiler, Kompilierungsoptionen usw. basiert, sehen Sie unterschiedliche Nummern aus demselben Code, aber unterschiedliche Compiler, aber jedes Mal, wenn gedruckt wird, ist dies festgelegt.Beim Kompilieren von Code ist mir aufgefallen, dass nach dem Beginn des Abschnitts Bytes
heap
platziert werden . Jedes Mal, wenn ich diesen Code ausführe, endet meine Adresse mit .0x8B0
.data
0x8B0
quelle
heap
wenn sie sich nicht im Heap befindet?Der Compiler hat zufällig einen
heap
Offset von 0x60 Bytes in ein Datensegment eingefügt, möglicherweise weil der Compiler in den ersten 0x60 Bytes einige andere Dinge hat, wie z. B. Daten, die von dem Code verwendet werden, der diemain
Routine startet . Deshalb sehen Sie "060"; es ist genau dort, wo es zufällig war, und es hat keine große Bedeutung dafür.Durch die Randomisierung des Adressraumlayouts werden die Basisadressen geändert, die für verschiedene Teile des Programmspeichers verwendet werden. Dies geschieht jedoch immer in Einheiten von 0 x 1000 Byte (da dadurch Probleme mit der Ausrichtung und andere Probleme vermieden werden). Sie sehen also, dass die Adressen um ein Vielfaches von 0x1000 schwanken, aber die letzten drei Ziffern ändern sich nicht.
Die Definition
static int heap[SOME_VAR];
definiertheap
mit statischer Speicherdauer. Typische C-Implementierungen speichern es in einem allgemeinen Datenabschnitt, nicht im Heap. Der "Heap" ist eine Fehlbezeichnung für Speicher, der für die dynamische Zuordnung verwendet wird. (malloc
Dies ist eine Fehlbezeichnung, da Implementierungen eine Vielzahl von Datenstrukturen und Algorithmen verwenden können, die nicht auf Heaps beschränkt sind. Sie können sogar mehrere Methoden in einer Implementierung verwenden.)quelle