Hallo, ich bin immer noch dabei C++ zulernen und hab definitiv immer
noch Probleme mit Pointern.
In der Qt Dokumenation zum QByteArray constdata steht, dass es ein
Zeiger auf die Daten ist und die Gültigkeit solange besteht wie das
QByteArray nicht zerstört wurde.
Mit statischen Daten klappt alles wunderbar, nun bekomme ich woanders
her die Daten und würde Sie gerne übergeben.
Dein Memory-Management ist generell ziemlich wirr. Wo soll das Ergebnis
des Casts denn leben?
Ich glaube ich würde in diesem Fall das Ergebnis einfach nach dem Cast
kopieren:
const MyClass d = *reinterpret_cast<MyClass*>(byteArr.data());
speicherst du einen Pointer auf deine Daten irgendwo hin und erwartest
dann hier
1
SendData(protocolclass)
das deine Daten in einem bis jetzt komplett unbeteiligten Objekt stehen?
Versuch noch einmal deinen Code etwas aufgeräumter zu gestalten, so wird
dir wahrscheinlich keiner helfen können. Generell gilt auch, dass casts
praktisch nie eine gute Idee sind.
Ähnlich hatte ich es auch am Anfang gedacht, aber das gibt die
Fehlermeldung
Semantic Issue
reinterpret_cast from type 'const char *' to MyClass* casts away
qualifiers
Unbeteiligt ist es doch nicht nach meinem Verständnis. Mein Verständnis
ist, dass der void* databytes Pointer auf den Speicherbereich der
MyProtocolclass zeigt, welches wiederum ein Buffer ist. Der
Speicherbereich wird auf die Struktur (MyDataclass) gecastest und ich
kann die Werte dementsprechend ändern.
Oder ist mein Verständnis falsch?
Vielleicht erklärst du erstmal was du eigentlich erreichen willst, weil
das ist alles irgendwie ein bisschen wirr was du da machst. Bei dem Code
oben fehlt irgendwo ein const oder es ist wo eins zu viel, du kannst dir
ziemlich aussuchen welches du weg oder hin machst ;)
>Vielleicht erklärst du erstmal was du eigentlich erreichen willst, weil>das ist alles irgendwie ein bisschen wirr was du da machst. Bei dem Code>oben fehlt irgendwo ein const oder es ist wo eins zu viel, du kannst dir>ziemlich aussuchen welches du weg oder hin machst ;)
Ok, zweiter Versuch:
In dem Beispiel setze ich Werte im Struct MyDataclass manuell und sende
Sie per Ethernet an ein Gerät. Die Klasse MyProtoclass ist gegeben und
beinhaltet den kompletten Protokolloverhead und die Nutzdaten für das
Gerät.
Das Beispiel orientiert sich am Hersteller des Gerätes und Protokolls
zum Daten senden, klappt auch wunderbar.
Ich bekomme nun von anderen Applikationen nur die Nutzdaten als
QByteArray und möchte die einfach übergeben und an das Gerät senden.
Das hier klappt auch wunderbar und es werden die Werte aus dem
QByteArray an das Gerät gesendet:
Diesen Teil würde ich gerne ändern und die Daten im QByteArary direkt
auf die Struktur kopieren und senden, ohne jeden einzeln Index
anzugeben.
Hier ist auch der Nachteil, wenn die Struktur z.B. ein uint16 beinhaltet
würde es mit dem Index gar nicht gehen.
Ist es jetzt nicht möglich einfach die Daten im QByteArray auf die
Struktur MyDataClass zu kopieren? Ich würde kein Index benötigen und ich
könnte auch unterschiedliche Typen z.B. uint16 übergeben.
Thorben schrieb:> databytes = protocolclass.Adddata(id,size);> myDataclass* wdata = reinterpret_cast<MyDataclass*>(databytes);> memcpy(wdata,ba.data(),size);
Gut, dass du den wdata Pointer zwischen der 2. und 3. Zeile nicht
dereferenzierst. Das macht die 2. Zeile allerdings auch überflüssig.
>Ne das ist kaputt, das geht so nicht. Überleg doch mal wo das memcpy>eigentlich hin kopiert.
Läuft seit 18:00 Uhr im Dauerlauftest mit Werteänderungen im QByteArray.
Die erste Stunde gab es keine Probleme und mehr weiss ich erst am
Montag.
Thorben schrieb:> Das Memcpy kopiert das ByteArray auf den Speicherbereich wdata.
wdata ist ein Pointer kein Speicherbereich. Dieser Pointer zeigt
hoffentlich auf einen zulässigen Speicherbereich. Was genau dieses
Addddata zurück gibt, weißt nur du.
Wenn die Addata Funtkion einen void* zurück gibt, ist der
reinterpret_cast unnötigt. Liefert sie etwas anderes zurück, hast du
vermutlich undefined behaviour.
Du hast natürlich recht wdata ist ein Pointer und der Pointer zeigt auf
den Speicherbereich.
>Wenn die Addata Funtkion einen void* zurück gibt, ist der>reinterpret_cast unnötigt.
Addata gibt ein void* zurück, welcher auf den Speicherbereich des
dynamischen Buffers in der Protokolklasse zeigt.
Ich glaube hier hast du ebenfalls vollkommen recht. Ich denke der
reinterpret_cast wird nur benötigt, wenn man gerne über die Struktur
darauf zugreifen möchte.
Ich werde es am Montag probieren direkt die Daten im QByteArray.data()
mit memcopy zukopieren.
Thorben schrieb:> Addata gibt ein void* zurück, welcher auf den Speicherbereich des> dynamischen Buffers in der Protokolklasse zeigt.
Du solltest bei der Gelegenheit auch nochmal über deine Namen
nachdenken. Ich habe mit Absicht einmal Addata und einmal Addddata
geschrieben ;-) Bei SendData kommt man nicht so leicht durcheinander.
Thorben schrieb:> Wenn ich nun die Daten aus dem QByteArray nehme, dann wird das> QByteArray natürlich zerstört und die Daten sind weg.
Nein, das QByteArray wird zerstört, wenn die Funktion beendet ist.
SendData() wird vor dem Beenden der Funktion aufgerufen.
Früher war das einfacher. Da hat man ein char Array genommen und fertig.
Heute wird das in
const QByteArray &ba
gepackt. Und mit
MyDataclass* wdata = reinterpret_cast<MyDataclass*>(databytes);
gecastet.
Intern passiert wahrscheinlich das gleiche, als hätte man ein char Array
genommen hätte. Nur durchblicken tut das keiner mehr.
Am besten programmiert man noch einen Iterator anstelle des memcpy.
Mein Fazit: Nehmt die Komplexität raus, dann versteht ihr euren eigenen
Code wieder.
Thorben schrieb:> Ich glaube hier hast du ebenfalls vollkommen recht. Ich denke der> reinterpret_cast wird nur benötigt, wenn man gerne über die Struktur> darauf zugreifen möchte.
Nein, das Dereferenzieren von wdata wäre sofort UB (undefined
behaviour).
Ansonsten liest sich dein Code ein wenig wie diese
Gehirn-Trainings-Spielchen wo man den Namen einer Farbe in einem
farbigen Text lesen soll. Also quasi "rot-blau-grün", der Text ist aber
blau-grün-rot geschrieben...
PittyJ schrieb:> Früher war das einfacher. Da hat man ein char Array genommen und fertig.
Da müsste man aber von Hand malloc und free machen und sich überlegen,
wer dafür verantwortich ist. Wäre also umständlicher.
> Heute wird das in> const QByteArray &ba> gepackt. Und mit> MyDataclass* wdata = reinterpret_cast<MyDataclass*>(databytes);> gecastet.
Ein Cast wäre so oder so nötig. Der hier ist klarer als ein klassischer
C-Style-Cast, weil er genauer aussagt, was hier passiert.
> Intern passiert wahrscheinlich das gleiche, als hätte man ein char Array> genommen hätte. Nur durchblicken tut das keiner mehr.
Du solltest nicht von dir auf andere schließen.
> Am besten programmiert man noch einen Iterator anstelle des memcpy.
Das wäre auch nicht sonderlich dramatisch und hätte mit std::copy
gegenüber memcpy den Vorteil, dass es Typsicherheit bietet. Bei memcpy
muss ich für die Benutzung ja erstmal den Typ komplett über Bord werfen.
Rolf M. schrieb:> Thorben schrieb:>> Wenn ich nun die Daten aus dem QByteArray nehme, dann wird das>> QByteArray natürlich zerstört und die Daten sind weg.>> Nein, das QByteArray wird zerstört, wenn die Funktion beendet ist.> SendData() wird vor dem Beenden der Funktion aufgerufen.
Wieso wird das QByteArry zerstört?
Das wird als const Referenz an die Funktion
handlemessage() übergeben.
Da der TO keine Infos zum Kontext des Aufrufes
liefert, kann man darüber keine Aussage treffen.
merciless
Dirk K. schrieb:>> Nein, das QByteArray wird zerstört, wenn die Funktion beendet ist.>> SendData() wird vor dem Beenden der Funktion aufgerufen.>> Wieso wird das QByteArry zerstört?> Das wird als const Referenz an die Funktion> handlemessage() übergeben.
Da hast du natürlich recht. Das QByteArray wird in der Funktion gar
nicht zersört.
> Da der TO keine Infos zum Kontext des Aufrufes> liefert, kann man darüber keine Aussage treffen.
Naja, so oder so ist es beim Aufruf von SendData noch existent.