Warum ändert sich die Adresse des Parameters der Hauptfunktion jedes Mal?
-
25-09-2019 - |
Frage
Ich schreibe einen Test, der den Inhalt von argv[0] – die Adresse des Parameters der Hauptfunktion – wie folgt ausgibt:
printf("%p\n",argv[0]);
Ich habe das Programm mit Visual Studio 2008 unter Windows 7 kompiliert.
Dann habe ich das Programm 1000 Mal ausgeführt und die Ergebnisse in eine Datei ausgegeben.Dadurch ändert sich die Adresse von argv[0], einige Adressen sind jedoch gleich und wiederholen sich etwa zehnmal.
Warum ändert sich die Adresse des Parameters der Hauptfunktion jedes Mal?
Lösung
Interessante Frage, sehe ich nur sehr wenige oder gar keine Gründe für die Nicht-Determinismus, dass in eigenen Adressraum des Programms. Aber ich werde Ihnen sagen, was ich weiß.
Als erstes argv zugeordnet, erstellt und initialisiert sich nicht durch Fenster, sondern durch STDC Laufzeit. Was wiederum wirft eine andere Frage - nicht lpCmdLine Parameter von winmain auch ändern? Im moment gibt es mehrere andere Variablen auf dem gleichen Heap zugewiesen, wahrscheinlich Umgebung Vars werden ebenfalls kopiert. Einer von ihnen muss eine Größe haben, je nach dem Fall der Ausführung.
Wie auch immer, warum grübeln Blackbox? Wo ist dein Disassembler, Soldat?
Andere Tipps
argc
und argv
sollten auf den Stapel gelegt werden, bevor die von der Hauptroutine der binären ausführbaren beginnen. Eigentlich denke ich, dass argv
dynamisch irgendwo in dem Heap zugeordnet wird und dann wird der Zeiger auf den Stapel gelegt.
Das bedeutet, dass der Haufen Allocator ist derjenige, der kümmert sich um, wo die Daten zugeordnet ist und aus diesem Grund ändert jedes Mal (es von der Politik abhängt) .. Ihr Programm wird dem OS bitten, den Raum für die Argumente zuweisen (man denke etwa durch malloc
vorbei), so kann es interne Entscheidungen sein, hergestellt nach etwas (wie die ASLR sie sprachen)
Hier ist zunächst einmal der Sprachstandard (n1256) muss sagen:
5.1.2.2.1 Programmstart
...
2 Wenn sie deklariert werden, müssen die Parameter für die Hauptfunktion den folgenden Einschränkungen befolgen:
- Der Wert von
argc
soll nicht negativ sein.
argv[argc]
soll ein Nullzeiger sein.
- Wenn der Wert von
argc
ist größer als Null, die Array-Mitgliederargv[0]
durchargv[argc-1]
Inklusive müssen Zeiger auf Zeichenfolgen enthalten, die vor dem Programm Startup implementiert werden.Die Absicht ist es, die vor dem Programm Startup von anderen Gegenden in der gehosteten Umgebung festgelegten Programminformationen zu liefern.Wenn die Wirtsumgebung nicht in der Lage ist, Saiten mit Buchstaben in Großbuchstaben und Kleinbuchstaben zu liefern, muss die Implementierung sicherstellen, dass die Zeichenfolgen in Kleinbuchstaben empfangen werden.
- Wenn der Wert von
argc
ist größer als Null, die Zeichenfolge, auf die gezeigt wirdargv[0]
repräsentiert die Programmname;argv[0][0]
soll der Nullcharakter sein, wenn der Programmname nicht in der Hostumgebung verfügbar ist.Wenn der Wert vonargc
ist größer als eins, auf die Saiten hingewiesen durchargv[1]
durchargv[argc-1]
repräsentieren die Programmparameter.
- Die Parameter
argc
Undargv
und die Zeichenfolgen, auf die die zeigtargv
Array ist durch das Programm verändert und behält ihre zuletzt gelagerten Werte zwischen Programmstart und Programmabschluss bei.
Der letzte Punkt ist der interessanteste in Bezug auf Wo die übergebenen String-Argumente main
sind gelagert.Sie müssen veränderbar sein und eine statische Ausdehnung haben, wodurch ihre Position im Speicher eingeschränkt wird.Es gibt jedoch keine Anforderung seitens der Sprachdefinition, dass sie sich jedes Mal, wenn das Programm ausgeführt wird, am selben Ort befinden.
Ich habe MSDN flüchtig durchsucht, um zu sehen, ob dort etwas explizites steht, habe aber noch nichts gefunden.Es kommt wahrscheinlich auf ASLR an, wie in den Kommentaren zum OP erwähnt.