Reihenfolge von globalen Objekten
-
Abend,
ich habe den globalen operator new überschrieben. Vereinfacht, so:
void* operator new(size_t size) { return g_Allocator.alloc(size); }g_Allocator ist ein globales Objekt (mein Allokator, der per malloc() etc. speicher allokiert).
Nur bin ich mir nicht sicher, ob das funktioniert falls es irgendwo andere globale Objekte geben sollte, die im Ctor new benutzen. Z.B. sowas:
class Foo { public: int* p; Foo() { p = new int; } }; ... Foo g_Foo; // globales FooDie Reihenfolge, in der globale Objekte erzeugt werden, ist ja undefiniert. Es könnte jetzt ja sein, dass g_Foo VOR meinem Allokator erzeugt wird. D.h. operator new() wird aufgerufen und dann g_Allocator.alloc(), obwohl g_Allocator noch NICHT erzeugt wurde.
- Kann das passieren? Oder hab ich was übersehen und kann dieses Szenario garnicht auftreten?
- Wenn es passiert kann, was passiert dann? Sprich was passiert wenn g_Allocator.alloc() aufgerufen, obwohl g_Allocator noch nicht erzeugt wurde. Segmanation fault?
- Wie könnte ich das lösen?
-
- Ja, kann passieren, wenn die Objekte in verschiedenen Übersetzungseinheiten liegen.
- Undefiniertes Verhalten - das heißt von Speicherlecks bis zu einem Bluescreen ist alles möglich
- vermeide globale Variablen (eine Alternative sind Singletons).
-
Danke für die Antwort!
Naja, da operator new() eine globale Funktion ist, MUSS auch mein Allokator global sein.
Meinst du mit Singleton statt dem hier:void* operator new(size_t size) { return g_Allocator.alloc(size); }das:
static Allocator& Allocator::getInstance() { static Allocator a; return a; } void* operator new(size_t size) { return Allocator::getInstance().alloc(size); }?
-
MichiU schrieb:
Danke für die Antwort!
Naja, da operator new() eine globale Funktion ist, MUSS auch mein Allokator global sein.
Wer sagt das? Wichtig ist nur, daß der Allokator dort erreichbar ist, wo du ihn benötigst.
Meinst du mit Singleton statt dem hier:
void* operator new(size_t size) { return g_Allocator.alloc(size); }das:
static Allocator& Allocator::getInstance() { static Allocator a; return a; } void* operator new(size_t size) { return Allocator::getInstance().alloc(size); }?
Vereinfacht gesagt: Ja.
PS: Hast du eigentlich einen tieferen Grund, warum du die C++ Speicherverwaltung selber übernehmen willst? Und hast du auch daran gedacht, den operator delete und die Array-Versionen von new/delete zu überladen?
-
CStoll schrieb:
Wer sagt das? Wichtig ist nur, daß der Allokator dort erreichbar ist, wo du ihn benötigst.
Öhh, wie sollte ich denn in operator new() sonst meinen Allokator erreichen, wenn er nicht global ist?
CStoll schrieb:
Vereinfacht gesagt: Ja.
Klingt so, als wäre das noch immer problematisch?
CStoll schrieb:
PS: Hast du eigentlich einen tieferen Grund, warum du die C++ Speicherverwaltung selber übernehmen willst? Und hast du auch daran gedacht, den operator delete und die Array-Versionen von new/delete zu überladen?
Ich mach es vor allem aus Debug/Tracing Gründen. Und ja, alle anderen operator new/delete sind auch überladen.
-
MichiU schrieb:
CStoll schrieb:
Wer sagt das? Wichtig ist nur, daß der Allokator dort erreichbar ist, wo du ihn benötigst.
Öhh, wie sollte ich denn in operator new() sonst meinen Allokator erreichen, wenn er nicht global ist?
CStoll schrieb:
Vereinfacht gesagt: Ja.
Klingt so, als wäre das noch immer problematisch?
Das Fragment selber ist nicht problematisch, du mußt nur darauf achten, daß der Rest des Singleton auch in Ordnung ist (sprich: getInstance() ist die einzige Methode, die in der Lage ist einen Allokator anzulegen).
Und in den Code hast du auch schon den Trick angewendet, wie man ein nicht-globales Objekt erreichen kann
CStoll schrieb:
PS: Hast du eigentlich einen tieferen Grund, warum du die C++ Speicherverwaltung selber übernehmen willst? Und hast du auch daran gedacht, den operator delete und die Array-Versionen von new/delete zu überladen?
Ich mach es vor allem aus Debug/Tracing Gründen. Und ja, alle anderen operator new/delete sind auch überladen.
Dann hoffe ich aber auch, daß die alloc()-Methode ihren Speicher nicht selber per new/delete besorgt (sowohl den von außen angeforderten als auch die eigenen Zusatzinfos).