Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

YAR

Frischling

  • »YAR« ist der Autor dieses Themas
  • Private Nachricht senden

1

30.11.2016, 21:20

Gleichbleibende Speicheradresse bei lokalem statischem Zeiger

Hallo :)

nachdem ich das Kapitel 8.4, Singletons, in "C++ für Spieleprogrammierer" durchgearbeitet hatte, habe ich mir mal auf Gameprogrammingpatterns deren Implementierung angesehen und habe danach den folgenden Code erstellt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class singleton
{
public:
    static singleton& instance()
    {
        static singleton *instance = new singleton;
        cout << "Adresse von Zeiger instance = " << &instance << endl;
        cout << "Adresse der Instanz = " << instance << endl;
        return *instance;
    }
    
    void textausgabe()
    {
        cout << "Hat funktioniert!" << endl;
    }
    
    
private:
    int zahl;
    
    singleton() 
    {
        cout << "Konstruktor von Singleton aufgerufen." << endl;
    }
};

int main()
{
    singleton &referenz = singleton::instance();
    singleton &zweite_referenz = singleton::instance();
    
    referenz.textausgabe();
}


Der Code ist nur als Test gedacht und verfolgt nur einen Zweck: Ich versuche(!) zwei Instanzen des Singletons zu erstellen und lasse mir die Speicheradressen ausgeben, um anzuzeigen, ob es funktioniert oder nicht.

Inzwischen habe ich herausgefunden, wie dieser Singleton funktioniert, doch was mir dabei auffiel ist, dass die Adresse des Zeigers *instance bei jeder erneuten Ausführung des kompilierten Programmes gleich bleibt.
Hier mal die relevante Ausgabe:

Zitat

$ ./Programme/c++/singleton
Konstruktor von Singleton aufgerufen.
Adresse von Zeiger instance = 0x6021b8
...

$ ./Programme/c++/singleton
Konstruktor von Singleton aufgerufen.
Adresse von Zeiger instance = 0x6021b8
...


Ich kann nur vermuten, dass der statische lokale Zeiger über die Laufzeit des Programmes hinaus erhalten bleibt. Aber warum? Hängt das vielleicht damit zusammen, wie Linux seinen Speicher verwaltet? Oder interpretiere ich die Ausgabe falsch?
Die Adresse, auf die der Zeiger deutet, variiert im übrigen, so wie ich es erwartet hätte.

Kurz zu meiner Umgebung:
Betriebssystem: Arch Linux mit KDE
Compiler: gcc (g++)

Offtopic:
Das ist das erste Mal, dass mich ein Forum meinen Beitrag nicht posten lässt wegen eines Rechtschreibfehlers :D
Das muss so!

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

30.11.2016, 21:43

Es bleibt nicht erhalten. Dein Programm wird aber immer an dieselbe virtuelle Basis-Adresse geladen und da der Pointer statisch ist und nicht dynamisch im Heap, hat er auch immer wieder dieselbe Adresse relativ zum Programm. Somit also effektiv dieselbe virtuelle Adresse. Alles, was per "new" erzeugt wird, liegt irgendwo zufällig in freiem Heap.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

3

30.11.2016, 21:48

Es ist definitiv nicht garantiert, dass die Adresse bei erneuter Ausfuehrung erhalten bleibt, aber es kann durchaus vorkommen.

Ich denke es passiert das folgende (Mein Wissen hier ist etwas Lueckenhaft, daher keine Garantie):

Deine static instance ist im data segment deiner executable gespeichert, d.h. wird zusammen mit der executable in den Speicher geladen wenn die executable ausgefuehrt wird.

Linux schmeisst deine exec nicht direkt aus dem Speicher nachdem sie ausgefuehrt wurde, sondern nur wenn der Speicher knapp wird. Wenn du sie also wieder neu ausfuehrst, muss sie nicht nochmal von der HDD geladen werden. Daher ist auch die adresse deiner static instance im data segment noch die selbe.

Wie du richtig erwartet hast variiert die gespeicherte adresse selbst, da diese dynamisch mit new angelegt wird und nicht 'statisch' im data segment liegt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

30.11.2016, 22:08

Ich denke nicht, dass das was mit "im Speichr bleiben" zu tun hat. Wie ich schon sagte vermute ich hier eher, dass die Executable an dieselbe *virtuelle* Basis-Adresse geladen wird bei jedem Start. Zumindest unter Windows ist das nach meiner Erfahrung üblich.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Tobiking

1x Rätselkönig

  • Private Nachricht senden

5

01.12.2016, 07:25

Bei den meisten Systemen ist der Standard ein festes (virtuelles) Speicherlayout, wie BluCobold schon sagte. Der vom Compiler/Linker generierte Maschinencode ist dabei sogar davon abhängig das es so ist. Optional bieten die meisten Systeme aber inzwischen als Sicherheitsfeature an bei jedem Start der Anwendung die Startadressen der verschiedenen Bereiche zufällig zu wählen (siehe ASLR). Du kannst mal probieren ob es tut wenn du dem gcc -fPIE als zusätzlichen Parameter mit gibst. Das hängt zusätzlich allerdings auch noch davon ab wie die verwendeten Bibliotheken gebaut wurden und was im Kernel aktiviert ist.

YAR

Frischling

  • »YAR« ist der Autor dieses Themas
  • Private Nachricht senden

6

01.12.2016, 13:24

Vielen Dank für die Aufklärung :)

Ich hatte schon befürchtet, ich muss sogar bei solchen kleinen Experimenten aufpassen, ob der Speicher vernünftig aufgeräumt wurde.
Das muss so!

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

01.12.2016, 18:55

Das hängt davon ab, was genau du erwartest. Das System wird den Speicher auf jeden Fall wieder für andere Programme zur Nutzung freigeben. Es wird aber nicht die Werte, die von dir in den Speicher geschrieben wurden, bei der Freigabe mit irgendwas überschreiben, damit niemand anderes sie lesen kann.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

YAR

Frischling

  • »YAR« ist der Autor dieses Themas
  • Private Nachricht senden

8

02.12.2016, 11:57

Es ging mir nur um eventuelle Speicherüberläufe. Ich hatte mich zwar vorher informiert, ob Betriebssysteme nach Programmende den Speicher wieder freigeben, war aber durch die Angelegenheit mit den Speicheradressen etwas verunsichert.

Meine Programme sind noch nicht an dem Punkt, an dem ich ihnen irgendwelche sicherheitsrelevante Aufgaben zuteilen würde ;)
Das muss so!

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

03.12.2016, 05:15

Wie gesagt: Du solltest dich über virtuelle Speicherverwaltung informieren. Die Speicheradressen, die du in deinem Programm siehst, haben nur für deinen Prozess eine Bedeutung. Sie sind rein virtuell und haben nichts mit der tatsächlichen physikalischen Adresse innerhalb der RAM-Module zu tun. Die Speicherbereiche der Prozesse sind voneinander abgeschottet. Du kannst dein Programm auch mehrfach parallel starten, und trotzdem wird jede Instanz ihre Variablen an derselben Adresse sehen, trotzdem sind sie unabhängig voneinander.

YAR

Frischling

  • »YAR« ist der Autor dieses Themas
  • Private Nachricht senden

10

03.12.2016, 11:07

Danke für den Tipp :)

Ich merke, es gibt noch so einiges, in das ich mich reinlesen muss.
Das muss so!

Werbeanzeige