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 

array aus unterschieldlichen klassen...
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Torsten Robitzki
Guest





PostPosted: Mon Sep 18, 2006 8:10 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote



Ernst Murnleitner wrote:

Quote:
B: Es wäre ziemlich übel, wenn undefiniertes Verhalten auftreten würde
und der Compiler das vorher durchgehen hätte lassen. Was soll den da
passieren? Oder würde der Speicher gar nicht vollständig freigegeben
(kann ich mir ja eigentlich nicht vorstellen, das wäre ganz ganz übel).

Man könnte sich z.B. einen Fall vorstellen, in dem der Compiler Code
generiert, der für jedes delete den Zeiger nur in eine Liste mit freien
Speicherstücken hängt (aus denen dann bei Bedarf wieder
Speicheranforderungen befriedigt werden). Da zur Übersetzungszeit
bekannt ist, wie groß das Stück speicher ist, kann er für jede Größe
eine eigene Liste führen. Für

struct A {
virtual ~A() {}
};

struct B : A {
int i;
};

sei mal angenommen, das A 8 Byte groß und B 16 Byte groß wäre. Der
Compiler generiert Destruktoren, die einen zusätzlichen, unsichtbaren
Parameter haben (meiner macht das tatsächlich so), der angibt, ob der
Speicher frei gegeben werden soll. Das sähe dann evtl. so aus:

void A_destr(bool del, A* this) {
if ( del ) delete_8(this);
}

void B_destr(bool del, B* this) {
A_destr(false, this);
if ( del ) delete_16(this);
}

Wenn Du jetzt den Compiler dazu bringst A_destr() für ein B aufzurufen,
hängt plötzlich ein 16 Byte großes Stück Speicher in der Liste der 8
Byte großen, freien Speicherstücke => Speicherleck.

Ist aber eigentlich mühsig darüber zu sinnieren, was da konkret schief
gehen kann. Undefiniert ist undefiniert und da darf per Definition nach
halt alles passieren Wink.

mfg Torsten
Back to top
Bob Hairgrove
Guest





PostPosted: Tue Sep 19, 2006 12:35 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote



On Mon, 18 Sep 2006 00:20:00 +0200, Ernst Murnleitner <mur (AT) awite (DOT) de>

wrote:



Quote:
Meinst Du A)

unerwünscht, weil nicht alle Konstruktoren aufgerufen werden oder B)

undefiniert?



B.



--

Bob Hairgrove

NoSpamPlease (AT) Home (DOT) com
Back to top
Ernst Murnleitner
Guest





PostPosted: Tue Sep 19, 2006 12:51 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote



Hallo,


Quote:
void A_destr(bool del, A* this) {
if ( del ) delete_8(this);
}

void B_destr(bool del, B* this) {
A_destr(false, this);
if ( del ) delete_16(this);
}

Wenn Du jetzt den Compiler dazu bringst A_destr() für ein B aufzurufen,
hängt plötzlich ein 16 Byte großes Stück Speicher in der Liste der 8
Byte großen, freien Speicherstücke => Speicherleck.


Das heist also, dass der Compiler den Code zum löschen zum Destruktor
hinzufügt? Wenn eine beliebige andere Funktion virtuell definiert ist,
dann wüsste ja sonst das System auch, welche Klasse das ist. Wenn ich es
mir überlege, wäre es aber sicher am einfachsten, den Code zum
Destruktor hinzuzugeben.

Ernst
Back to top
Ernst Murnleitner
Guest





PostPosted: Tue Sep 19, 2006 12:57 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Hallo,

Quote:
Oder würde der Speicher gar nicht vollständig freigegeben
(kann ich mir ja eigentlich nicht vorstellen, das wäre ganz ganz übel).


Wieso wäre das ganz übel?
Das ist Stand der aktuellen Software. Frag mal JAVA-Entwickler...

Weil das sehr leicht Fehler passieren können. Ich dachte mir immer, ich
muss nur darauf achten, den Destruktor virtuell zu deklarieren, wenn ich
darin auch Code habe, der was aufräumt. Bei einem leeren Destruktor
dachte ich wäre das egal. Ich war der Meinung, der Desktruktor ist nur
was zusätzliches, dass Zeiger und Größe des Speicherbereiches irgendwie
anders verwaltet werden.

Ich habe irgendwo ein Speicherleck, welches ich nicht finde und aufgrund
von Smartpointern dürfte es das gar nicht geben. Das wäre dann ein Grund.

Ernst
Back to top
Ernst Murnleitner
Guest





PostPosted: Tue Sep 19, 2006 1:06 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Hallo,


Quote:

Das Verhalten ist nicht undefiniert, es ist definiert!

Und zwar wird bei

.....
Und dann:

A* a = new B;
delete a;

Nicht ~B() aufgerufen, sondern nur ~A(). D.h. falls B Speicher
dynamisch anfordert, wird dieser nicht freigegeben.
Falls ~A() virtual ist, dann wird erst ~B() und dann ~A() aufgerufen.

Das dachte ich mir auch. Aber die beiden anderen im anderen
Antwort-Zweig hatten es so beschrieben, als wie wenn dann evt. nicht der
ganze Speicher freigegeben wird, obwohl A und B selbst keinen Speicher
mit new allozieren.

Was stimmt nun?

Ernst
Back to top
Bob Hairgrove
Guest





PostPosted: Tue Sep 19, 2006 1:12 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

On Mon, 18 Sep 2006 00:20:00 +0200, Ernst Murnleitner <mur (AT) awite (DOT) de>

wrote:



Quote:
Was meinst Du mit "verursacht undefiniertes Verhalten"?



Im C++-Standard: bitte bei §5.3.3 nachschlagen!



--

Bob Hairgrove

NoSpamPlease (AT) Home (DOT) com
Back to top
Bob Hairgrove
Guest





PostPosted: Tue Sep 19, 2006 1:14 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

On Mon, 18 Sep 2006 00:20:00 +0200, Ernst Murnleitner <mur (AT) awite (DOT) de>

wrote:



Quote:
"verursacht undefiniertes Verhalten"?



Sorry, das in meiner letzten Nachricht sollte §5.3.5 Absatz 3 heißen!



--

Bob Hairgrove

NoSpamPlease (AT) Home (DOT) com
Back to top
Torsten Robitzki
Guest





PostPosted: Tue Sep 19, 2006 2:00 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Ernst Murnleitner wrote:

Quote:

Hallo,


void A_destr(bool del, A* this) {
if ( del ) delete_8(this);
}

void B_destr(bool del, B* this) {
A_destr(false, this);
if ( del ) delete_16(this);
}

Wenn Du jetzt den Compiler dazu bringst A_destr() für ein B
aufzurufen, hängt plötzlich ein 16 Byte großes Stück Speicher in der
Liste der 8 Byte großen, freien Speicherstücke => Speicherleck.



Das heist also, dass der Compiler den Code zum löschen zum Destruktor
hinzufügt?

Es ist Aufgabe des Compilers, aus dem was Du schreibst lauffähigen Code
zu machen. Letztendlich Maschinencode. Du hattest nach _einer_
Möglichkeit gefragt, was undefiniert praktisch noch anderes bedeuten
könnte als das für Member der abgeleiteten Klasse der Destruktor nicht
aufgerufen wird. Die Funktionen ?_destr, sollten den Kode eines vom
Compiler generierten Destruktor darstellen. Sorry, wenn das so nicht
klar geworden ist.

Quote:
Wenn eine beliebige andere Funktion virtuell definiert ist,
dann wüsste ja sonst das System auch, welche Klasse das ist. Wenn ich es
mir überlege, wäre es aber sicher am einfachsten, den Code zum
Destruktor hinzuzugeben.

? Wenn der Destruktor virtuell ist, wird für ein delete auf eine Zeiger
auf A, der in Wirklichkeit auf ein B zeigt, der Destruktor B::~B()
ausgeführt, (in meinem Beispiel die Funktion B_destr()), ohne virtuellen
d'tor eben der von A.

mfg Torsten
Back to top
Thomas Thiele
Guest





PostPosted: Tue Sep 19, 2006 3:39 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Torsten Robitzki schrieb:

Quote:
Das Verhalten ist nicht undefiniert, es ist definiert!

Wo?

Im Standard?

Ich bin der Meinung - und das war bislang auch immer so - dass der
Destructor diesbezüglich wie eine normale Funktion behandelt wird. Mit
dem Unterschied dass bei der virtuellen Variante die ganze
Klassenhierachie aufgerufen wird.
Back to top
Falk Tannhäuser
Guest





PostPosted: Tue Sep 19, 2006 4:15 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Thomas Thiele schrieb:
Quote:
Bob Hairgrove schrieb:
Das hat
zur Folge, daß der Destruktor in der virtuellen Basisklasse ebenfalls
virtuell (d.h. mit dem Schlüsselwort "virtual") deklariert und
implementiert werden *muß* ... sonst verursacht es undefiniertes
Verhalten, wenn ein solcher Zeiger mit "delete" verwendet wird. Dabei
kann der Rumpf der Implementierung des Destruktors auch leer sein.

Das Verhalten ist nicht undefiniert, es ist definiert!

Wo? In § 5.3.5/3 jedenfalls nicht!
"Undefined behaviour" beinhaltet eben auch, dass es u.U. funktionieren
kann wie erwartet, woraus man jedoch leider nicht schlussfolgern kann,
dass dies immer so bleibt...
Folgendes stürzt z.B. mit GCC schmählich ab:

#include <iostream>
#include <ostream>

struct A
{
int i;
A() { std::cout << "A::A()" << std::endl; }
~A() { std::cout << "A::~A()" << std::endl; }
};

struct B : public A
{
B() { std::cout << "B:B()" << std::endl; }
~B() { std::cout << "B::~B()" << std::endl; }
virtual void foo() {}
};

int main()
{
A* a = new B;
delete a;
std::cout << "Und tschüss!" << std::endl;
return 0;
}

Der Grund ist, dass 'a' hier nicht auf den Anfang des vom vollständigen
'B'-Objekt eingenommenen Speicherblocks zeigt (Klasse 'B' ist im
Gegensatz zu 'A' polymorph, und GCC packt den Vtable-Zeiger an den
Anfang des 'B'-Objekts, d.h. vor das 'A'-Unterobjekt), was beim
Freigeben nicht so gut kommt. Eine ähnliche Situation kann bei
Mehrfachvererbung oder virtueller Vererbung eintreten. Die Anwesenheit
eines virtuellen Destruktors in der Basisklasse sorgt in jedem Falle
dafür, dass die richtige Adresse (der Anfang des allozierten
Speicherblocks) an die Freigabefunktion übergeben wird.

Weiterhin gestattet C++ ja bekanntlich das klasseweise Redefinieren der
Allozierungs- und Freigabefunktionen 'operator new()' und 'operator
delete()', wobei dann von einem delete-Ausdruck der richtige 'operator
delete()' abhängig vom dynamischen Typen des betreffenden vollständigen
Objekts aufgerufen werden muss. Dies dürfte praktisch mit den meisten
Compilern nur klappen, wenn der Basisklassendestruktor virtuell ist.

MfG
Falk
Back to top
Heinz Saathoff
Guest





PostPosted: Tue Sep 19, 2006 12:17 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Bob Hairgrove schrieb...
Quote:
Was meinst Du mit "verursacht undefiniertes Verhalten"?



Im C++-Standard: bitte bei §5.3.3 nachschlagen!

Ich frag mich, warum das als 'undefiniertes Verhalten' bezeichnet wird.
Wenn keiner der Klassen einen Destruktor benötigt, weil keine Resourcen
freizugeben sind, sollte es doch vollkommen definiert sein?

Einzig bei Mehrfachableitungen und definierten Destruktoren ist ohne
'virtual' undefiniert, für welche Teilobjekte der Destruktor tatsächlich
ausgeführt wird. Aber auch hier sollte gelten: Wenn keiner der Klassen
in der Ableitung einen Destruktor benötigt, sollte das Verhalten
definiert sein.


- Heinz
Back to top
Thomas Thiele
Guest





PostPosted: Tue Sep 19, 2006 2:54 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Ernst Murnleitner schrieb:

Quote:
Das dachte ich mir auch. Aber die beiden anderen im anderen
Antwort-Zweig hatten es so beschrieben, als wie wenn dann evt. nicht der
ganze Speicher freigegeben wird, obwohl A und B selbst keinen Speicher
mit new allozieren.

Vermutlich ist das compiler-abhängig.

Ich versuch mal einen educated guess:

Wenn ich ein B Objekt habe und der Comiler nur den aktuellen statischen
Typ A vor sich sieht, dann räumt nur die A-Teile auf. Und wenn jetzt
der Compiler zusätzlich zu den eigl. B-Membern noch
Verwaltungsoverhead (virtual function table und so'n Zeug...) anlegt,
dann bleibt das eventuell auch stehen.

Falls meine Vermutung richtig ist, dann müsste das Verhalten
(Speicherlecks) unterschiedlich sein wenn virtuelle Funktion im Spiel
sind oder nur nicht virtuelle, also keine späte Bindung erfolgt und
damit kein Verwaltungsoverhead notwendig wird.

Kann jemand der mehr als nur raten kann, dass mal bestätigen oder
korrigieren?
Back to top
Thomas Thiele
Guest





PostPosted: Tue Sep 19, 2006 10:48 pm    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Falk Tannhäuser schrieb:

Quote:
"Undefined behaviour" beinhaltet eben auch, dass es u.U. funktionieren
kann wie erwartet, woraus man jedoch leider nicht schlussfolgern kann,
dass dies immer so bleibt...
Folgendes stürzt z.B. mit GCC schmählich ab:

Ups. Hab ich das Beispiel grad selber ausprobiert. (gcc version 3.4.4
unter Cygwin)

Wieder was gelernt. Hätt ich von anschauen her nicht vermutet.

Werde das morgen mal mit VC++ probieren.
Back to top
Georg Maaß
Guest





PostPosted: Wed Sep 20, 2006 12:11 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

Heinz Saathoff wrote:

Quote:
Aber auch hier sollte gelten: Wenn keiner der Klassen
in der Ableitung einen Destruktor benötigt, sollte das Verhalten
definiert sein.

Aber das kannst Du doch gar nicht wissen, weil Die Tatscahe, daß Du
einen leeren Destruktor-Body implementiert hast, bedeutet doch nicht,
daß der Kompiler nicht noch irgendwas drum herum macht, was er für nötig
hält, was aber keine Entsprechung in Deinem Quelltext hat.

Diese Kompiler spezifischen Unbekannten führen dazu, daß es beim einen
Kompiler funktionieren kann, aber nicht garantiert ist, daß es bei jedem
funktioniert.

Sowas ist schlicht weg undefiniert.
Back to top
Bob Hairgrove
Guest





PostPosted: Wed Sep 20, 2006 1:26 am    Post subject: Re: array aus unterschieldlichen klassen... Reply with quote

On 19 Sep 2006 10:48:41 -0700, "Thomas Thiele" <jana.luetz (AT) gmx (DOT) de>
wrote:

Quote:
Werde das morgen mal mit VC++ probieren.

Warum? Es ist immer noch undefiniertes Verhalten; auch dann, wenn es
(zufällig) mit diesem Compiler zu funktionieren scheint.

--
Bob Hairgrove
NoSpamPlease (AT) Home (DOT) com
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
 


Powered by phpBB © 2001, 2006 phpBB Group