andere static variablen
-
funky cat schrieb:
Was soll da schlimmes passieren? Der Text wird ausgegeben und fertig.
Ich denke, dass er meint, dass es abhängig von der Implementation des Compilers entweder ausgegeben wird (ctor aufgerufen) oder eben nicht. Also nicht im Standard definiert ist, was da passiert.
-
Das ist doch Quatsch. Der Ctor vom globalen Objekt wird aufgerufen bevor main aufgerufen wird. Ich glaube nicht daß irgendein Compiler das nicht macht.
-
funky cat schrieb:
Das ist doch Quatsch. Der Ctor vom globalen Objekt wird aufgerufen bevor main aufgerufen wird. Ich glaube nicht daß irgendein Compiler das nicht macht.
Das ist auch nicht das Problem, drakon hat vielmehr noch nicht viel Bekanntschaft mit Dieter Nuhr geschlossen.
#include <iostream> struct Foo { Foo() { foovar = 1; } static int foovar; }; int Foo::foovar = 0; struct Bar { Bar() { barvar = Foo::foovar; } static int barvar; }; int Bar::barvar = 0; Foo foo; Bar bar; int main() { std::cout << Bar::barvar << std::endl; // 0 or 1? }
-
Hier noch ein einfacher zu verstehendes Beispiel:
struct Foo { Foo(); }; Foo bar; #include <iostream> Foo::Foo() { std::cout << "Hallo!\n"; } int main() {}$ g++ --version
i686-apple-darwin8-g++-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5370)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.$ g++ -Wall test.cpp -o test
$ ./test
Segmentation fault
-
Keine globalen Variablen. Fertig.
-
funky cat schrieb:
Das ist doch Quatsch. Der Ctor vom globalen Objekt wird aufgerufen bevor main aufgerufen wird. Ich glaube nicht daß irgendein Compiler das nicht macht.
Natürlich wird der Konstruktor aufgerufen, das ist auch nicht das Problem. Das Problem ist, dass nicht definiert ist, ob die globale Variable cout zu diesem Zeitpunkt bereits initialisiert ist, denn:
asc schrieb:
Bei globalen Variablen ist die Initialisierungsfolge undefiniert
-
Edit: Sorry, hatte nur auf die Änderungsmeldung geklickt, Antwort existerte schon xD... Wenn man unter Streß ist...
funky cat schrieb:
asc schrieb:
b) Bei globalen Variablen ist die Initialisierungsfolge undefiniert
was aber völlig egal ist, weil alle globalen Variablen spätestens dann initialisiert sind, wenn "main" aufgerufen wird.
Eben nicht. Wir hatten schon einmal im Projekt einen Fehler der annährend 2 Wochen zur Lokalisierung brauchte.
Nehmen wir einfach mal an wir haben zwei globale Instanzen von Klassen in unterschielichen Headern. Ein globales Objekt braucht im Konstruktor die Instanz des anderen:
// In unterschiedlichen Headern: A globalesA; B globalesB(globalesA);Nun kann folgendes passieren, da die Reihenfolge undefiniert ist:
a) "globalesB" hat eine gültige Instanz von A
b) "globalesB" hat eine ungültige Instanz von AViel Spaß bei der Fehlersuche.
Eine Mögliche Lösung ist folgende:
A& GetAInstanz() { static A a; return a; } B& GetBInstanz() { static B b(GetAInstanz()); return b; }Hier ist nämlich definiert: Anlage beim ersten Aufruf...
cu André
-
asc schrieb:
funky cat schrieb:
asc schrieb:
b) Bei globalen Variablen ist die Initialisierungsfolge undefiniert
was aber völlig egal ist, weil alle globalen Variablen spätestens dann initialisiert sind, wenn "main" aufgerufen wird.
Eben nicht. Wir hatten schon einmal im Projekt einen Fehler der annährend 2 Wochen zur Lokalisierung brauchte.
2 Wochen!!!? oha, vielleicht hättet ihr euch doch mal eher ansehen sollen, wie ein Debugger funktioniert.
Na gut. C++ Merkregel Nr. 7831: Niemals in konstruktoren von globalen Objekten andere globale Objete benutzen. Bei einfachen Variablen, int, long, double und so weiter sollte es aber trotzdem gehen.
-
Babyentenwickler schrieb:
funky cat schrieb:
Das ist doch Quatsch. Der Ctor vom globalen Objekt wird aufgerufen bevor main aufgerufen wird. Ich glaube nicht daß irgendein Compiler das nicht macht.
Das ist auch nicht das Problem, drakon hat vielmehr noch nicht viel Bekanntschaft mit Dieter Nuhr geschlossen.
#include <iostream> struct Foo { Foo() { foovar = 1; } static int foovar; }; int Foo::foovar = 0; struct Bar { Bar() { barvar = Foo::foovar; } static int barvar; }; int Bar::barvar = 0; Foo foo; Bar bar; int main() { std::cout << Bar::barvar << std::endl; // 0 or 1? }1. Immer schön sachlich bleiben.
2. Gibt das 1, wie es sein soll. Es wird initialisert nach der Reihenfolge, wie es im Code steht.
Das Problem entsteht nur, wenn die Objekte in unterschiedlichen Objekten stehen. DORT ist es nicht definiert, welches globale Objekt initialisiert wird. (wie asc bereits geschrieben hat).
2 Wochen!!!? oha, vielleicht hättet ihr euch doch mal eher ansehen sollen, wie ein Debugger funktioniert.
Ich denke, dass die sehr genau wissen, wie ein Debugger funktioniert. Das Problem war eher, dass, wenn man es nicht weiss diesen Fehler hald nicht findet, weil man davon ausgeht, dass es so stimmen muss. Und ich denke mal nicht, dass der Debugger da eine grosse Hilfe wäre.
Na gut. C++ Merkregel Nr. 7831: Niemals in konstruktoren von globalen Objekten andere globale Objete benutzen. Bei einfachen Variablen, int, long, double und so weiter sollte es aber trotzdem gehen.
Ok, sofern sie in unterschiedlichen Übersetzungseinheiten deklariert sind. Innerhalb einer Übersetzungseinheit sollte das aber kein Problem sein.
-
drakon schrieb:
Babyentenwickler schrieb:
Das ist auch nicht das Problem, drakon hat vielmehr noch nicht viel Bekanntschaft mit Dieter Nuhr geschlossen.
#include <iostream> struct Foo { Foo() { foovar = 1; } static int foovar; }; int Foo::foovar = 0; struct Bar { Bar() { barvar = Foo::foovar; } static int barvar; }; int Bar::barvar = 0; Foo foo; Bar bar; int main() { std::cout << Bar::barvar << std::endl; // 0 or 1? }1. Immer schön sachlich bleiben.
2. Gibt das 1, wie es sein soll. Es wird initialisert nach der Reihenfolge, wie es im Code steht.
So ich muss mal keine Babys in Schutz nehmen.
Es ist hier nicht definiert ob 1, oder 0 ausgeben wird. Falls zuerst das globale Obejekt bar instanziert wird, dann ist Bar::barvar 0. Wenn davor schon foo instanziert wurde, dann ist Bar::barvar 1.
Dass du weiter behauptest, Du hättest Recht und Tatsachen nicht einsiehst ist wirklich faszinierend.
-
es ist garantiert, dass foo vor bar initialisiert wird. (3.6.2/1)
-
Die dynamische Initialisierung von Objekten in Namensräumen, die in der gleichen Übersetzungseinheit definiert werden, erfolgt in der Reihenfolge, in der diese Definitionen in dieser Übersetzungseinheit auftreten (3.6.2/1). Nominell werden hier die Objekte foo und bar dynamisch initialisiert. Das Ergebnis kann allerdings trotzdem 0 oder 1 sein, da eine Implementation unter bestimmten Voraussetzungen Objekte, die eigentlich dynamisch initialisiert werden, statisch zu initialisieren [queer_boy: Grundregel für alle Jura-Studenten - immer den ganzen Paragraphen lesen
]. Diese Voraussetzungen sind aber nicht so strikt wie die as-if-Regel, nämlich:
1. die dynamische Version der Initialisierung darf den Wert anderer Namensraumobjekte vor deren (dynamischer) Initialisierung nicht verändern (das kann nur dann problematisch sein, wenn irgendwelche Vorwärtsdeklarationen im Spiel sind); hier verändert der Konstruktor Bar den Wert des Objektes Bar::barvar, dieses wurde aber bereits statisch mit 0 initialisiert, also kein Hindernis
2. die statische Version der Initialisierung muss das betreffende Objekt mit dem gleichen Wert initialisieren, den es hätte, wenn alle Objekte, die nicht statisch initialisiert werden müssen, dynamische initialisiert würden (in der Reihenfolge ihrer Definitionen) - bar hat ohnehin keinen eigenen Wert, also auch kein Problem
Folglich darf bar hier statisch initialisiert werden, falls aber foo dann im Anschluss dynamisch initialisiert wird, ergibt sich als Ergebnis der Ausgabe 0.
-
queer_boy schrieb:
es ist garantiert, dass foo vor bar initialisiert wird. (3.6.2/1)
Danke, das habe ich jetzt gesucht.

-
camper schrieb:
da eine Implementation unter bestimmten Voraussetzungen Objekte, die eigentlich dynamisch initialisiert werden, statisch zu initialisieren [queer_boy: Grundregel für alle Jura-Studenten - immer den ganzen Paragraphen lesen
].das habe ich sogar getan

irgendwie hab ich nach dem drüberlesen sowohl (1) als auch (2) ausgeschlossen. hm.