Zerstörungsreihenfolge von statischen Objekten in C++

Lesezeit: 6 Minuten

Zerstorungsreihenfolge von statischen Objekten in C
Gal Goldmann

Kann ich die Reihenfolge steuern, in der statische Objekte zerstört werden? Gibt es eine Möglichkeit, meine gewünschte Bestellung durchzusetzen? Zum Beispiel auf irgendeine Weise festzulegen, dass ein bestimmtes Objekt zuletzt zerstört werden soll oder zumindest nach einem anderen statischen Objekt?

Die statischen Objekte werden in umgekehrter Reihenfolge des Aufbaus zerstört. Und die Baureihenfolge ist sehr schwer zu kontrollieren. Sie können sich nur sicher sein, dass zwei in derselben Übersetzungseinheit definierte Objekte in der Reihenfolge ihrer Definition aufgebaut werden. Alles andere ist mehr oder weniger zufällig.

  • Es gibt Techniken, um das Problem zu umgehen, wenn Sie eine Bestellung benötigen: siehe stackoverflow.com/questions/335369/…

    – Martin York

    22. Januar 2009 um 20:33 Uhr

  • I -1, weil diese Antwort nicht wirklich eine Antwort auf die Frage des OP ist.

    – Benutzer2746401

    15. Oktober 2014 um 13:23 Uhr

  • Technisch die Vervollständigung des Destruktors geschieht in umgekehrter Reihenfolge Fertigstellung des Konstrukteurs. Dies macht einen Unterschied in dem Fall, in dem ein statisches Objekt während des Konstruktors eines anderen initialisiert wird. Siehe C++14 [basic.start.term]/1

    – MM

    16. Juli 2015 um 0:43 Uhr

  • Antworte mir wenn möglich einfach; Wenn ich statisches Objekt ‘a’ bzw. ‘b’ konstruiert habe, jetzt, wenn ‘a’ vor ‘b’ zerstört wird, unabhängig davon, wie dies passieren kann. Ist das Programm fehlerhaft?

    – 0x0

    11. Dezember 2021 um 11:03 Uhr

Die anderen Antworten darauf bestehen darauf, dass dies nicht möglich ist. Und sie haben laut Spezifikation Recht – aber da ist ein Trick, mit dem Sie es tun können.

Erstellen Sie nur a Einzel statische Variable einer Klasse oder Struktur, die all die anderen Dinge enthält, die Sie normalerweise statische Variablen erstellen würden, etwa so:

class StaticVariables {
    public:
    StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { };
    ~StaticVariables();

    Var1Type *pvar1;
    Var2Type *pvar2;
};

static StaticVariables svars;

Sie können die Variablen in beliebiger Reihenfolge erstellen, und was noch wichtiger ist, zerstören sie in beliebiger Reihenfolge im Konstruktor und Destruktor für StaticVariables. Um dies vollständig transparent zu machen, können Sie auch statische Verweise auf die Variablen erstellen, wie folgt:

static Var1Type &var1(*svars.var1);

Voilà – totale Kontrolle. 🙂 Dies ist jedoch zusätzliche Arbeit und im Allgemeinen unnötig. Aber wenn es ist notwendig, es ist sehr nützlich, darüber Bescheid zu wissen.

  • Hmmm — wenn *pvar1 und *pvar2 die statischen Variablen sind, deren Konstruktions- und Zerstörungsreihenfolge Sie steuern möchten, kann ich nicht umhin zu bemerken, dass Sie dieses Problem gelöst haben, indem Sie sie nicht mehr statisch gemacht haben ;-). Ihre Klasse wird tatsächlich oft überhaupt nicht benötigt: Wenn Sie alle Variablen in derselben Übersetzungseinheit haben können (was aufgrund von zirkulären Header-Abhängigkeiten möglicherweise unmöglich ist), könnten Sie sie einfach deklarieren, was die Konstruktions- (und damit Zerstörungs-) Reihenfolge perfekt definiert .

    – Peter – Setzen Sie Monica wieder ein

    6. August 2020 um 5:14 Uhr

  • Ihr Klassentrick ist nur erforderlich und möglich, wenn (1) Ihre Objekte dynamisch konstruiert werden können und nicht zu viele Informationen benötigen, um konstruiert zu werden (die normalerweise nur in ihrer “natürlichen” TU verfügbar sind); (2) ob alle benötigten Header koexistieren können; (3) wenn tatsächlich keine Umkehrung einer möglichen Baureihenfolge zu Ihrer benötigten Zerstörungsreihenfolge passt.

    – Peter – Setzen Sie Monica wieder ein

    6. August 2020 um 5:15 Uhr

Zerstorungsreihenfolge von statischen Objekten in C
ChrisW

Statische Objekte werden in umgekehrter Reihenfolge zerstört, in der sie erstellt wurden (z. B. das zuerst erstellte Objekt wird zuletzt zerstört), und Sie können die Reihenfolge steuern, in der statische Objekte erstellt werden, indem Sie die in Punkt 47 beschriebene Technik verwenden. “Stellen Sie sicher, dass globale Objekte initialisiert werden, bevor sie verwendet werden“ in Meyers’ Buch Effektives C++.

Zum Beispiel in irgendeiner Weise festzulegen, dass ich möchte, dass ein bestimmtes Objekt zuletzt zerstört wird, oder zumindest nach einem anderen statischen Objekt?

Stellen Sie sicher, dass es vor dem anderen statischen Objekt erstellt wird.

Wie kann ich die Baureihenfolge kontrollieren? nicht alle Statiken befinden sich in derselben DLL.

Ich ignoriere (der Einfachheit halber) die Tatsache, dass sie sich nicht in derselben DLL befinden.

Meine Paraphrase von Meyers Punkt 47 (der 4 Seiten lang ist) lautet wie folgt. Angenommen, Ihr Global ist in einer Header-Datei wie dieser definiert …

//GlobalA.h
extern GlobalA globalA; //declare a global

… fügen Sie dieser Include-Datei Code wie diesen hinzu …

//GlobalA.h
extern GlobalA globalA; //declare a global
class InitA
{
  static int refCount;
public:
  InitA();
  ~InitA();
};
static InitA initA;

Dies hat zur Folge, dass jede Datei, die GlobalA.h enthält (z. B. Ihre GlobalB.cpp-Quelldatei, die Ihre zweite globale Variable definiert), eine statische Instanz der InitA-Klasse definiert, die vor allem anderen darin erstellt wird Quelldatei (z. B. vor Ihrer zweiten globalen Variablen).

Diese InitA-Klasse hat einen statischen Referenzzähler. Wenn die erste InitA-Instanz erstellt wird, was jetzt garantiert vor der Erstellung Ihrer GlobalB-Instanz erfolgt, kann der InitA-Konstruktor alles tun, was er tun muss, um sicherzustellen, dass die globalA-Instanz initialisiert wird.

Kurze Antwort: Generell nein.

Etwas längere Antwort: Für globale statische Objekte in einer einzelnen Übersetzungseinheit ist die Initialisierungsreihenfolge von oben nach unten, die Zerstörungsreihenfolge ist genau umgekehrt. Die Reihenfolge zwischen mehreren Übersetzungseinheiten ist undefiniert.

Wenn Sie wirklich eine bestimmte Reihenfolge benötigen, müssen Sie diese selbst erstellen.

Es gibt keine Möglichkeit, dies in Standard-C++ zu tun, aber wenn Sie über gute Kenntnisse Ihrer spezifischen Compiler-Interna verfügen, kann dies wahrscheinlich erreicht werden.

In Visual C++ befinden sich die Zeiger auf die statischen Init-Funktionen in der .CRT$XI Segment (für statische Initialisierung vom Typ C) oder .CRT$XC Segment (für statische Init vom C++-Typ) Der Linker sammelt alle Deklarationen und fügt sie alphabetisch zusammen. Sie können die Reihenfolge steuern, in der die statische Initialisierung erfolgt, indem Sie Ihre Objekte im richtigen Segment mit deklarieren

#pragma init_seg

Wenn Sie beispielsweise möchten, dass die Objekte von Datei A vor denen von Datei B erstellt werden:

Datei A.cpp:

#pragma init_seg(".CRT$XCB")
class A{}A;

Datei B.cpp:

#pragma init_seg(".CRT$XCC")
class B{}B;

.CRT$XCB wird vorher zusammengeführt .CRT$XCC. Wenn die CRT die Zeiger der statischen Init-Funktion durchläuft, trifft sie auf Datei A vor Datei B.

In Watcom ist das Segment XI und Variationen von #pragma initialize können die Konstruktion steuern:

#pragma initialize before library
#pragma initialize after library
#pragma initialize before user

…weitere Informationen finden Sie in der Dokumentation

1646260212 13 Zerstorungsreihenfolge von statischen Objekten in C
Gemeinschaft

Lesen:
SO-Initialisierungsreihenfolge

SO Lösung des Problems der Initialisierungsreihenfolge

1646260213 635 Zerstorungsreihenfolge von statischen Objekten in C
Martin Cott

Nein, das kannst du nicht. Sie sollten sich niemals auf die andere Konstruktion/Zerstörung statischer Objekte verlassen.

Sie können immer einen Singleton verwenden, um die Reihenfolge der Konstruktion/Zerstörung Ihrer globalen Ressourcen zu steuern.

916800cookie-checkZerstörungsreihenfolge von statischen Objekten in C++

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy