C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Zugriff auf unvollständig kosntruiertes Objekt erlaubt stand

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Thu Apr 19, 2007 1:06 pm    Post subject: Zugriff auf unvollständig kosntruiertes Objekt erlaubt stand Reply with quote



Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?

Beispiel:
f greift auf das globale Objekt a zu, bevor das globale Objekt a
fertig konstruiert worden ist:


#include <iostream>
void f();
class A
{
public:
A()
{
m=5;
f();
}
void g()
{
std::cout << "m=" << m << std::endl;
}
private:
int m;
};

static A a;
void f()
{
a.g();
}

int main()
{
return 0;
}
Back to top
Marcel Müller
Guest





PostPosted: Fri Apr 20, 2007 12:33 am    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote



zei2006q1 (AT) liwest (DOT) at wrote:
Quote:
Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?

Die entscheidende Frage ist /wie/.

Quote:
Beispiel:
f greift auf das globale Objekt a zu, bevor das globale Objekt a
fertig konstruiert worden ist:

#include <iostream
void f();
class A
{
public:
A()
{
m=5;
f();
}
void g()
{
std::cout << "m=" << m << std::endl;
}
private:
int m;
};

static A a;
void f()
{
a.g();
}

int main()
{
return 0;
}

In diesem Beispiel wird es definiertes Verhalten sein, da a::m bereits
konstruiert ist. Und das liegt nicht daran, dass vor dem Aufruf von f()
m=5 steht, sondern daran, dass vor dem Eintritt in den Konstruktor von
A() /alle/ Basisklassen und Elemente fertig konstruiert sind und dass es
nur ein statisches Objekt von A gibt. Dass m nach der eben genannten
Konstruktion erstmal einen undefinierten Wert hat, ist eine Eigenheit
des POD-Typs int, die in diesem Zusammenhang keine Rolle spielt.

Wenn hingegen mehr als ein statisches Objekt von A existiert, wird es
eng. Da die Initialisierungsreihenfolge derselben nur in bestimmten
Ausnahmefällen definiert ist, hat man schnell undefiniertes Verhalten.

Von der Sache her ist es natürlich etwas unlogisch, dass der Konstruktor
jedes beliebigen A eine Methode eines im allgemeinen anderen A aufruft.
Dabei verliert man i.A. die Threadsicherheit auf Instanzebene - also
verschiedene Threads dürfen nicht unsynchronisiert mit /verschiedenen,/
privaten Instanzen von A arbeiten. Aber das ist ein anderes Thema. Die
Eigentümlichkeit mag sich aber auch mit dem auf das wesentliche
Reduzierten Beispiel ergeben haben. Eine statische Methode g() hätte ich
eher verstanden.

Problematischer wird die Sache, wenn man vor dem Eintritt in den
Konstruktor auf die eigene Klasse zugreift. Z.B. so:

class A : public B
{public:
A() : B(this) { ... }
...
};

Und jetzt B::B() irgendwas mit A treibt.
(Oder analog für Member von A.)

Das gibt je nach Compiler denn auch schon mal eine Warnung.

Es ist natürlich nicht damit zu rechnen, dass A an jeder beliebigen
Stelle des Konstruktors schon hinreichend lebensfähig ist, als dass alle
Methoden von A sich sinnvoll verhalten. Es obliegt aber im Ermessen der
Programmierers dafür zu sorgen, dass das gut geht. Nichts anderes wäre
passiert, wenn A::A() die Methode A::g() bzw. a.g() direkt aufgerufen
hätte - was logischerweise erstmal erlaubt ist. Ob dabei noch eine
andere Funktion dazwischen liegt, ist zweitrangig.

In jedem Fall ist es aber ein nicht sonderlich gut lesbarer
Programmierstil, wenn der Konstruktor von A die Initialisierungsprozedur
an Methoden außerhalb von A aus der Hand gibt.
Außerdem besteht auch ein besonderes Risiko, wenn die zu diesem
Zeitpunkt verwendeten Methoden von A virtuell sind und in Wirklichkeit
eine von A abgeleitete Klasse konstruiert werden soll. Da die
abgeleitete Klasse noch nicht konstruiert ist, können nämlich noch
keinerlei von ihr überladene Methoden aufgerufen werden. Und im
Spezialfall, dass die Methode in A sogar abstrakt ist, bekommt man dann
ganz schnell mal ein "virtual pure function called". Aber auch das gilt
auch, wenn A::A() die Methoden direkt aufruft. Es ist also keine
Besonderheit dieses Falls. Es ist nur weniger ersichtlich.

Also wie gesagt, kein doller Programmierstil, aber wenn man es richtig
macht, definiertes Verhalten. Und es gibt einige Gründe, wo eine solche
Lösung auch durchaus vertretbar ist. Beispielsweise, wenn der
Konstruktor etwas aufruft, was eine Callback-Methode (von A) benötigt.
In dem Fall kann der Konstruktor aber noch kontrollieren, welche
Methoden von A aufgerufen werden, und es ist deshalb auch kein
schlechter Stil.


Marcel
Back to top
Florian Kesseler
Guest





PostPosted: Fri Apr 20, 2007 2:38 am    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote



zei2006q1 (AT) liwest (DOT) at schrieb:
Quote:
Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?

Da der Standard nichts über Parallelität aussagt, ist es zwar erlaubt

(weil es eben nicht verboten ist), wird aber normalerweise nur zu
Problemen führen.

Bei Programmen, die in nur einem Thread laufen, kann das nicht
passieren, deshalb beachtet der Standard es nicht.
Back to top
Thomas Mang
Guest





PostPosted: Fri Apr 20, 2007 11:29 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote

Marcel Müller wrote:
Quote:
zei2006q1 (AT) liwest (DOT) at wrote:
Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?

Die entscheidende Frage ist /wie/.

Was in 3.8/6 näher erläutert wird.
Quote:

Beispiel:
f greift auf das globale Objekt a zu, bevor das globale Objekt a
fertig konstruiert worden ist:

#include <iostream
void f();
class A
{
public:
A()
{
m=5;
f();
}
void g()
{
std::cout << "m=" << m << std::endl;
}
private:
int m;
};

static A a;
void f()
{
a.g();
}

int main()
{
return 0;
}

In diesem Beispiel wird es definiertes Verhalten sein

In meinen Augen klar undef. Verhalten.
Da der Konstruktoraufruf noch nicht beendet wurde, hat die Lebenszeit
des Objektes a noch nicht begonnen. Da weiters auf ein non-static data
member zugegriffen wurde passt alles in 3.8/6 für UB zusammen.


Thomas
Back to top
Rolf Magnus
Guest





PostPosted: Sun Apr 22, 2007 1:14 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote

Thomas Mang wrote:

Quote:
Marcel Müller wrote:
zei2006q1 (AT) liwest (DOT) at wrote:
Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?

Die entscheidende Frage ist /wie/.

Was in 3.8/6 näher erläutert wird.

Beispiel:
f greift auf das globale Objekt a zu, bevor das globale Objekt a
fertig konstruiert worden ist:

#include <iostream
void f();
class A
{
public:
A()
{
m=5;
f();
}
void g()
{
std::cout << "m=" << m << std::endl;
}
private:
int m;
};

static A a;
void f()
{
a.g();
}

int main()
{
return 0;
}

In diesem Beispiel wird es definiertes Verhalten sein

In meinen Augen klar undef. Verhalten.
Da der Konstruktoraufruf noch nicht beendet wurde, hat die Lebenszeit
des Objektes a noch nicht begonnen.

Es kommt nicht darauf an, wann er beendet ist, sondern wann er anfängt (also
wann die Initialisierung der Members fertig ist). Siehe 12.7/1.
Back to top
Helmut Zeisel
Guest





PostPosted: Mon Apr 23, 2007 12:31 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt s Reply with quote

On 22 Apr., 10:14, Rolf Magnus <ramag...@t-online.de> wrote:

Quote:
Es kommt nicht darauf an, wann er beendet ist, sondern wann er anfängt (also
wann die Initialisierung der Members fertig ist). Siehe 12.7/1.

Interessant. Wenn ich 12.7/1 richtig versteihe,
ist das Codebeispiel also definiertes Verhalten.

Danke,

Helmut
Back to top
Thomas Mang
Guest





PostPosted: Mon Apr 23, 2007 5:41 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote

Rolf Magnus wrote:
Quote:
Thomas Mang wrote:

Marcel Müller wrote:
zei2006q1 (AT) liwest (DOT) at wrote:
Erlaubt der C++ Standard den Zugriff "von außen" auf ein Objekt,
dessen Konstruktor noch nicht vollständig durchlaufen worden ist?
Die entscheidende Frage ist /wie/.
Was in 3.8/6 näher erläutert wird.
Beispiel:
f greift auf das globale Objekt a zu, bevor das globale Objekt a
fertig konstruiert worden ist:

#include <iostream
void f();
class A
{
public:
A()
{
m=5;
f();
}
void g()
{
std::cout << "m=" << m << std::endl;
}
private:
int m;
};

static A a;
void f()
{
a.g();
}

int main()
{
return 0;
}
In diesem Beispiel wird es definiertes Verhalten sein
In meinen Augen klar undef. Verhalten.
Da der Konstruktoraufruf noch nicht beendet wurde, hat die Lebenszeit
des Objektes a noch nicht begonnen.

Es kommt nicht darauf an, wann er beendet ist, sondern wann er anfängt (also
wann die Initialisierung der Members fertig ist). Siehe 12.7/1.

Ich denke eher nicht.
Laut 3.8/1 fängt die Lebenszeit von non-PODs erst an, nachdem der
Konstruktoraufruf beendet wurde. Davor gelten Restriktionen - für Zeiger
3.8/5, für l-values 3.8/6. Ich interpretiere die Verwendung von a in f()
als l-value Verwendung gemäß 3.8/6, und da der Zugriff auf non-static
member stattfindet bevor der Konstruktoraufruf fertig ist, ist es als UB
definiert.
[Die wortwahl von 3.8/6 liest sich sehr nach Zugriff auf Objekten, die
'manuell' erzeugt und destruiert werden, also mit placement new und
direktem Destruktoraufruf. Ich denke aber nicht, dass es den hier
dargestellten Fall ausschließt - insbesondere weil die Wortwahl für
Zeiger anders, viel allgemeiner, ist].

Thomas
Back to top
Georg Maaß
Guest





PostPosted: Tue May 01, 2007 6:18 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote

Thomas Mang wrote:

Quote:
Ich denke eher nicht.

Warum ist der Standard so blöd formuliert, daß hochkomptetente Leute wie
Ihr darüber streiten müssen, was gemeint sein könnte; wie sollen dann
andere, die zwar auch viel Erfahrung haben, aber weniger kompetent sind,
das dann blicken?

Da ist doch was faul und erhebliches Verbesserungspotential im Standard
vorhanden, zumindest hinsichtlich der Formulierung.
Back to top
Marcel Müller
Guest





PostPosted: Fri May 04, 2007 11:34 pm    Post subject: Re: Zugriff auf unvollständig kosntruiertes Objekt erlaubt Reply with quote

Georg Maaß wrote:
Quote:
Warum ist der Standard so blöd formuliert, daß hochkomptetente Leute wie
Ihr darüber streiten müssen, was gemeint sein könnte; wie sollen dann
andere, die zwar auch viel Erfahrung haben, aber weniger kompetent sind,
das dann blicken?

Da ist doch was faul und erhebliches Verbesserungspotential im Standard
vorhanden, zumindest hinsichtlich der Formulierung.

Naja, warum glauben gerade wir deutschen, dass man jede Formulierung von
Anfang an so wählen kann, dass es absolut keine Zweifelsfälle mehr gibt.
Die Sprache ist nunmal nicht 100% eindeutig, und es ist auch reichlich
viel verlangt, dass man vorher immer an absolut alle potentiellen
Fragestellungen gedacht hat. Die Realität ist eine andere. Es gibt
manchmal Zweifelsfälle und man muss den Text auch interpretieren.
Sonst wäre die ganze Gruppe hier ja überflüssig.


Marcel
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.