Die statische int arr [10] -Speicheradresse endet immer mit 060

17

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

linuxlmao
quelle
2
Welches Betriebssystem? Welcher Compiler?
Andrew Henle
2
Die Variable befindet sich nicht im Heap, sondern im Daten- oder BSS-Bereich des Adressraums des Programms, siehe en.wikipedia.org/wiki/Static_variable . Ich vermute, dass das Programm immer an einer Speicheradresse an einer bestimmten Grenze platziert wird, z. B. durch 0x1000 teilbar, und die Variable vom Compiler mit einem festen Versatz im Adressraum des Programms platziert wird.
Bodo

Antworten:

15

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 heapbefindet 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.

Ctx
quelle
ASLR randomisiert die Ladebasis, wie ich mich erinnere. Die Abschnittsadresse basiert auf dieser Adresse.
Afshin
Ich verwende ein Buch über objektorientierte ANSI-C-Programmierung von Axel-Thobias Schreiner. Das Buch wurde ungefähr 1993 geschrieben. Wissen Sie, ob das Speicherlayout damals anders war? Wenn nicht, warum hätte er die Variable möglicherweise benannt, heapwenn sie sich nicht im Heap befindet?
Linuxlmao
Wird 4096 in irgendeiner Weise in 060 übersetzt oder wird 0x1000 in 060 übersetzt, sonst verstehe ich nicht, was Sie damit meinen, dass dies der Grund für das Ende ist? Ich dachte, es könnte damit zu tun haben, dass die Größe des Arrays etwas ist, das hexadezimal in 060 übersetzt wird, z. B. dezimal
linuxlmao
2
@linuxlmao Der Versatz beträgt beispielsweise 14060. Wenn Sie also ein Vielfaches einer Seitengröße (0x1000) hinzufügen, bleiben die letzten drei Ziffern erhalten 060.
Ctx
4

Wenn Sie Windows verwenden, liegt der Grund in der PE- Struktur.

Ihre heapVariable wird in einem .dataDateibereich 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 .dataAbschnitts, sodass die Adresse ein Vielfaches der Blockgröße beträgt.

Dies ist beispielsweise die Tabelle der kompilierten Windows-Version Ihres Codes: Abschnitte In diesem .textAbschnitt befindet sich Ihr kompilierter Code und .dataenthält Ihre heapVariable. Wenn Ihr PE in den Speicher geladen wird, werden Abschnitte unter einer anderen Adresse geladen, die von zurückgegeben wird VirtualAlloc()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 Adresse heapvon 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 heapplatziert werden . Jedes Mal, wenn ich diesen Code ausführe, endet meine Adresse mit .0x8B0.data0x8B0

Afshin
quelle
Ich verwende ein Buch über objektorientierte ANSI-C-Programmierung von Axel-Thobias Schreiner. Das Buch wurde ungefähr 1993 geschrieben. Wissen Sie, ob das Speicherlayout damals anders war? Wenn nicht, warum hätte er die Variable möglicherweise benannt, heapwenn sie sich nicht im Heap befindet?
Linuxlmao
2
@linuxlmao Es könnte anders gewesen sein. 1993 war Windows ein 16-Bit-Betriebssystem mit Speichersegmentierung und allerlei verwirrendem Material. Es war keine 32-Bit-Flat-Memory-Architektur wie jetzt. Diese Art von Dingen sind jedoch der Grund, warum das Stellen / Beantworten allgemeiner Fragen zum Layout einer Programmbinärdatei im Speicher nicht sinnvoll ist. Verstehen Sie, was der C-Sprachstandard Ihnen im Allgemeinen garantiert , und das ist alles, was Sie wissen müssen. Sorgen Sie sich nur um das tatsächliche Layout, wenn Sie ein bestimmtes Problem debuggen, und verwenden Sie dann einen Debugger
Cody Gray
Nein, die Variable sollte auch auf älteren Systemen nicht auf dem Heap erstellt werden, da sie nicht mit malloc zugewiesen wurde und eine statische Speicherdauer hat
phuclv
@Afshin Ich spreche den obigen Kommentar des OP an
phuclv
@phuclv Entschuldigung, weil Sie ihn nicht erwähnt wurden, dachte ich, Sie sprechen mich an. :)
Afshin
4

Der Compiler hat zufällig einen heapOffset 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 die mainRoutine 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];definiert heapmit 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. ( mallocDies 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.)

Eric Postpischil
quelle