reinterpret_cast bzw. memcpy fuer structs mit char[]
-
Hallo alle zusammen!
Ich arbeite seit geraumer Zeit schon an diesem problem und bin mir nicht sicher, ob ich den Grund fuer mein "Versagen" endlich gefunden habe. Also wollte ich mal die Allgemeinheit fragen (die sicherlich mehr weiss als ich).
Ich schreib das mal etwas grundlegender als in meinem Programm, damit das Einlesen nich ewig dauert:
Mein struct:
struct MyStruct { float a; long b; long c; char d[20]; char e[20]; float f; }Meine template-class:
template <class A> class MyClass { private: A* MyStructInClass; //class A ist das struct von oben public: void InitFromBuffer(char* Buffer); }Ich bekomme jetzt einen char-pointer mit der Byte-Laenge der struct in dem die Daten liegen, die ich benoetige und will diese in MyStructInClass speichern:
void MyClass<MyStruct>::InitFromBuffer(char* Buffer) { memcpy(this->MyStructInClass, Buffer, sizeof(MyStruct)); }Das klappt nicht (Fehler wegen korruptem Speicher). Liegt nach meiner Ansicht daran, dass ich versuche den Speicher eines members zu ueberschreiben.
Meine Alternative:
void MyClass<MyStruct>::InitFromBuffer(char* Buffer) { this->MyStructInClass = reinterpret_cast<MyStruct*>(Buffer); }Das klappt zwar ohne Runtime-Error, aber es steht meistens nich das gewuenschte in MyStructInClass:
a, b und c haben noch die korrekten Werte. Aber ab dem Array d stimmen die Werte nicht mehr.
Meine Begruendung:
C++ (bzw. .NET) verarbeitet char[20] als char*, d.h. man kann einen char[20] sowohl mit einem char* der Laenge 5 fuellen, als auch der Laenge 50. Zur Laufzeit wird der Speicher dynamisch angepasst.
Fuelle ich char d[20] mit "aaa", hat d die Groesse 3 Byte, bei "12345678901234567890123" die Groesse 23 Byte.
Prinzipiell macht das meine Metjode damit wohl nicht-implementierbar
-
Du hast einen Pointer - aber der zeigt zunächst noch nirgendwohin. Wenn du jetzt über diesen Pointer etwas schreiben willst, gibt's (mit etwas Glück) eine nette Fehlermeldung des Systems. Deshalb solltest du vor dem memcpy()-Aufruf erstmal genug Speicher für dein Struct anlegen, den du dann füllen kannst:
void MyClass<MyStruct>::InitFromBuffer(char* Buffer) { MyStructInClass = malloc(sizeof(MyStruct)); memcpy(this->MyStructInClass, Buffer, sizeof(MyStruct)); }(btw, wozu brauchst du eigentlich an der Stelle Templates?)
-
Zu der "abenteuerlichen" Vermutung

Nein, d ist immer 20 Bytes lang. Wenn Du nur 3 Bytes hineinschreibst, sind eben 17 Bytes "leer" (es steht das drin was vor dem kopieren auch drin stand - meistens Speichermüll), wenn Du 23 Bytes hineinschreibst, überschreibst Du die ersten drei Bytes von e.
-
Im eigentlichen Code gibt es mehrere (viele) structs die generiert werden aus einer Exel-Tabelle (projekt-abhaengig).
Durch das template koennten diese (halbwegs) dynamisch genutzt werden, und erspart damit eine Menge Arbeit weil man nicht antausenden Stellen alles neu implementieren muss.
-
@CStoll:
Danke fuer den Tipp! Nur ein kleiner Fehler war noch:void MyClass<MyStruct>::InitFromBuffer(char* Buffer) { MyStructInClass = (MyStruct*)malloc(sizeof(MyStruct)); memcpy(this->MyStructInClass, Buffer, sizeof(MyStruct)); }Bin aber noch net sicher, ob das laeuft, werds aber dann hier schreiben sobald ichs getestet habe.
@LordJaxom:
Die "abenteuerlichen" Vermutungen kommen immer dann, wenn man keinen Grund fuer Fehler findet
War bisher ja auch deiner Meinung, aber das hier liess mich zweifeln.
-
Ok, ich danke!!!
Die uebrigen Fehler liegen nich an mir
