PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++: Virtuelle Funktionen in Datenpaketen


Gast
2008-02-07, 13:32:16
Hi,

wenn ich eine Klasse als Datenpaket verschicken will (über sockets z.B.), kann ich ja Funktionen der Klasse definieren, die landen ja nicht in der Instanz d.h. belegen dort keine Byte.

Wenn dieses aber virtuelle Funktionen sind, müße doch die vtable in der Instanz gespeichert werden und damit auch im Datenpaket Platz wegnehmen, oder?

Was würde eigentlich passieren, wenn man so ein Paket jetzt wieder auf der anderen Seite empfängt und in ein Klasse dieser Familie castet. Kann die vtable noch richtig interpretiert werden oder zeigt das ins Nirvana?

danke

Trap
2008-02-07, 13:51:56
Das ganze Zeug was du beschreibst ist 100% compilerabhängig und im C++ Sprachstandard undefiniert.

Eventuell funktioniert es auch nur bei bestimmten Optimierungseinstellungen und in der nächsten Compilerversion garnicht mehr ;)

Gast
2008-02-07, 14:02:16
Vielen Dank! Ist nur der Teil mit dem Casten der vtable undefiniert, oder auch ob und wieviel Speicherplatz diese in einer Instanz belegt?

Kommunikationsparnter sind da BTW Visual Studio .NET x86 und linux gcc-4.1 x64. ;)

Coda
2008-02-07, 14:12:20
Alles undefiniert.

Trap
2008-02-07, 14:35:47
Wenn man unterschiedliche Compilereinstellungen/Compiler benutzt kann auch ohne vtable das Senden per Cast schief gehen.

Das hängt nämlich von der Größe der Datentypen und vom Layout der Structs ab und beides ist im C++ Standard nicht definiert.

Gast
2008-02-07, 14:41:37
Danke! In welchen Fällen kann die vtable vom Compiler denn komplett entfernt werden?

Mit #pragma pack(1) /* */ #pragma pack() wurden bei uns allerdings bisher immer die Datenbereiche zuverlässig an 1 Byte Grenzen ausgerichtet und keine Lücken gelassen.

Gast
2008-02-08, 09:45:32
Ist im C++ Standard eigentlich definiert, wenn man ohne Funktionen einfach nur von einer Klasse erbt, wie das Objekt aufgebaut ist?

Also z.B. erst alle Member der Mutterklasse, danach alle Member der jeweiligen Kindklasse?

malte.c
2008-02-08, 11:29:22
Danke! In welchen Fällen kann die vtable vom Compiler denn komplett entfernt werden?

Der Compiler kann, wenn er möchte, virtuelle Funktionen auch ganz ohne vtable über irgendeinen anderen Ansatz realisieren. vtables sind vom Standard nicht vorgeschrieben.

Gast
2008-02-08, 14:07:47
Hi,

wenn ich eine Klasse als Datenpaket verschicken will (über sockets z.B.), kann ich ja Funktionen der Klasse definieren, die landen ja nicht in der Instanz d.h. belegen dort keine Byte. wie willst du eine Instanz einer Klasse über Sockets verschicken? Sockets akzeptieren Byteströme, keine Objekte. Willst du mit memcpy das Objekt in ein char-Array kopieren, und auf der Gegenseite dann den Pointer auf den empfangenen String als Pointer auf eine Instanz behandeln, etwa so:

// Sender-Seite
MyClass myObject;
char *objectBuffer = new char[sizeof(MyClass)];
memcpy(objectBuffer, &myObject, sizeof(MyClass));
// objectBuffer via Socket versenden
// ...

// Empfänger-Seite
char* buffer;
// buffer aus Socket lesen
// ...
MyClass *myObject = (MyClass*) buffer;

? Halte ich für ... sagen wir, sehr abenteuerlich!

Ich an deiner Stelle würde, wenn immer nur Objekte einer bekannten Klasse verschickt werden sollen, ein Protokoll definieren, durch das jedes Objekt durch einen String repräsentiert wird. Hat die Klasse z.B. drei DatenMember var,var2,var3, könnte der String so aussehen: "Var1: ..., Var2: ..., Var3: ...".

Gast
2008-02-08, 19:21:12
? Halte ich für ... sagen wir, sehr abenteuerlich!
Hängt immer vom Anwendungsfall ab. Wenn sichergestellt ist, dass für beide Seiten der gleiche Compiler in der gleichen Version mit identischen Settings verwendet wird, ists vollkommen ok.
Falls man das nicht sicherstellen kann sind Crashs garantiert.

Ich an deiner Stelle würde, wenn immer nur Objekte einer bekannten Klasse verschickt werden sollen, ein Protokoll definieren, durch das jedes Objekt durch einen String repräsentiert wird. Hat die Klasse z.B. drei DatenMember var,var2,var3, könnte der String so aussehen: "Var1: ..., Var2: ..., Var3: ...".
Am Besten verpacken wir es noch in XML und schicken es im Klartext rüber?
Strings sind in der Regel die ineffizienteste Lösung, die es gibt.

Bietchiebatchie
2008-02-08, 21:57:38
Am Besten verpacken wir es noch in XML und schicken es im Klartext rüber?
Natürlich - wie denn sonst? Immer diese C++-Speed-Fanatiker ;)

maximAL
2008-02-08, 22:12:46
für sowas gibts auch serialization bibliotheken wie in boost...

Trap
2008-02-08, 22:16:17
Die Version mit pack() funktioniert solang die Datentypen die richtige Größe und Anordnung (high/low endian...) im Speicher haben. Hat aber eventuell Performancenachteile wenn man darauf arbeitet.

Die beste Variante (bei langsamer Verbindung und performancekritischen structs) ist die structs mit natürlichem alignment zu belassen und vor dem Versenden alle Daten in einen Puffer aneinanderzukopieren und auf der Gegenseite wieder auf das entsprechende alignment auseinanderzukopieren.