2014-01-16 10 views
6

In C++ Singleton design pattern erwähnt obecalp dass:Warum kann ein globales oder statisches Objekt beim Beenden des Programms zum Absturz führen?

Für viele größere Programme, insbesondere solche mit dynamischen Bibliotheken. Jedes globale oder statische Objekt, das kein primitives Element ist, kann beim Programm-Exit auf vielen Plattformen zu Segmentfehlern/Abstürzen führen, da die Bibliotheken beim Entladen beschädigt werden. Dies ist einer der Gründe, warum viele Kodierungskonventionen (einschließlich Googles) die Verwendung von nicht-trivialen statischen und globalen Objekten verbieten.

Kann jemand erklären, warum das passieren kann? Vielleicht ein Beispiel, um es zu erklären?

+0

Ein Beispiel von diesem ich angetroffen: Versuch, OpenGL-Funktionen von Singleton-Destruktor auszuführen - zu der Zeit Destruktor ausgeführt wurde, zerstörte Windows bereits das Fenster zusammen mit Rendering-Kontext und entladenen OpenGL-Bibliothek. – user2802841

Antwort

7

Möglicherweise haben Sie schon einmal von der static initialization order fiasco gehört, bei der ein global gebautes Objekt auf ein anderes globales verweist, das noch nicht gebaut wurde. Die allgemeine Lösung für dieses Problem besteht darin, faul initialisierte Objekte zu verwenden (Initialisierung bei der ersten Verwendung).

Nun, das gleiche Fiasko kann zur Zeit der Zerstörung auftreten, wenn der Destruktor eines Objekts auf ein anderes Objekt verweist, das bereits zerstört ist; und leider gibt es keine Silberkugellösung für dieses Problem, da der Code eines Destruktors beliebig komplex sein kann.

Eine Lösung ist einfach, die Verwendung dieser unmännlichen Eigenschaft zu verbieten.

+0

Dies ist der Hauptgrund, warum das tatsächliche Singleton-Objekt dynamisch zugewiesen und niemals gelöscht wird. –

+0

@JamesKanze: Leider verursacht dies auch Probleme; Sogar die Tatsache, dass der Destruktor tatsächlich ausgeführt werden soll (z. B. weil er Daten auf die Platte spült), wenn Sie Bibliotheken zur Laufzeit laden/entladen, wird sogar ignoriert. Eine Bibliothek, die die ihr zugewiesenen Singletons nicht richtig entsorgt, ist einfach *undicht*. –

+0

Wenn Sie eine Bibliothek ständig laden und entladen, haben Sie im Allgemeinen Probleme. Und während es Fälle gibt, in denen der Destruktor eines Singletons aufgerufen werden soll (ich habe einen, der temporäre Dateien verwaltet und der Destruktor sie löscht), sind sie eher die Ausnahme. Die meisten Singletons sollten nicht zerstört werden. (Und die meisten Bibliotheken sollten statisch verknüpft sein, damit das Problem des Ladens und Entladens nicht auftritt.) –

0

Ich bin Entsendung dies als eine Antwort, weil ich verstehe nicht, warum das nicht verwendet wird:

Einfach ein einziges globales Objekt auf dem Stapel machen (von einer Klasse) und weisen alle globalen Sie in diesem einen wollen (Mitgliedszeiger, auf Heap zugewiesen). Sie können Accessoren für diese globalen Objekte haben und sie dann im Destruktor des globalen Objekts zerstören, mit perfekter Kontrolle über die Reihenfolge ihrer Konstruktion/Dekonstruktion.

Oh, und übrigens, Sie können Schlösser auch dort, einschließlich zwischen den "globalen" Objekten haben.

Verwandte Themen