| Autor |
Beitrag |
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 19.08.07 10:47
Moin,
ich hab hier ein Problem beim Beschreiben / Füllen eines Buffers:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| class function encode16(Buf: PChar; Data: UInt16): PChar; var nData: UInt16; begin nData := htons(Data); Move(nData, Buf, SizeOf(UInt16)); Result := Buf + SizeOf(UInt16); end;
class function encode(Buf: PChar; const Data: PChar; aLength: Cardinal): PChar; begin Move(Data, Buf, aLength); Result := Buf + aLength; end;
function ( Buf: PChar; ): Cardinal; var Ptr, LengthP: PChar; begin Ptr := Buf; Ptr := encode16(Ptr, Msg.msgHdr.msgType);
LengthP := Ptr;
Ptr := encode16(Ptr, 0); Ptr := encode(Ptr, @Msg.msgHdr.msgId.Octet, SizeOf(Msg.msgHdr.msgId));
end; |
Ich bekomme eine Zugriffsverletzung, nachdem die markierte Zeile aufgerufen wurde und die Prozedur durchlaufen ist. Eigentlich ja auch irgendwie klar, es wurde bei den encode16-Prozeduren schon 4 von 4 Bytes beschrieben. Aber wie macht C++ das, bzw. warum funktioniert es ohne Fehlermeldung in C++? Hier das Original:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| static char* encode16(char* buf, UInt16 data) { UInt16 ndata = htons(data); memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16)); return buf + sizeof(UInt16); }
static char* encode(char* buf, const char* data, unsigned int length) { memcpy(buf, data, length); return buf + length; }
unsigned int ( char* buf, ) { char* ptr = buf;
ptr = encode16(ptr, msg.msgHdr.msgType);
char* lengthp = ptr; ptr = encode16(ptr, 0);
ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
} |
Falls ihr da noch mehr Infos / Source braucht, bitte sagen.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: So 19.08.07 11:42
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 19.08.07 11:53
Das habe ich schon fast vermutet. Aber wie muss ich es korrekt übergeben? Ein Cast auf PChar() funktioniert hier nicht. Und wie hat man reinterpret_cast zu verstehen?
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: So 19.08.07 12:09
GTA-Place hat folgendes geschrieben: | | Aber wie muss ich es korrekt übergeben? Ein Cast auf PChar() funktioniert hier nicht. |
Ein Cast auf PChar wäre aber eigentlich das, was notwenig ist. Warum geht das denn in Delphi nicht? | GTA-Place hat folgendes geschrieben: | | Und wie hat man reinterpret_cast zu verstehen? |
Wie einen typunsicheren Cast ohne static_cast<>.
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 19.08.07 13:39
Der Compiler meldet eine ungültige Typumwandlung. Eventuell ist Octet bei mir nicht der selbe Typ wie im Original. Ich prüfe das mal nach.
EDIT:
Gehen tut folgendes:
Delphi-Quelltext 1: 2:
| PChar(@Octet); PChar(Octet[0]); |
Stimmt die 1. Variante? Aber die ZV bleibt dann weiterhin bestehen.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 20.08.07 17:55
Sehr spezifisches Problem, trotzdem mal *push* 
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: Mo 20.08.07 18:05
GTA-Place hat folgendes geschrieben: | Gehen tut folgendes:
Delphi-Quelltext 1: 2:
| PChar(@Octet); PChar(Octet[0]); |
Stimmt die 1. Variante? |
Nein.
Welchen Typ hat msg.msgHdr.id.octet bei dir und im Original? Gehen solche komischen Tricks wie PChar(Pointer(octet))?
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 20.08.07 18:37
Octet ist bei mir ein Array[0..15] of Byte und im Original ein unsigned char octet[15]. Auch dieser PChar(Pointer())-Trick funktioniert nicht.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: Mo 20.08.07 18:47
GTA-Place hat folgendes geschrieben: | | Octet ist bei mir ein Array[0..15] of Byte und im Original ein unsigned char octet[15]. |
Ok, dann sollte PChar(@octet[0]) funktionieren. Aber warum hast du 16 Byte genommen und nicht auch 15?
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 20.08.07 18:52
Okay, das geht, aber die ZV bleibt.
tommie-lie hat folgendes geschrieben: | | Aber warum hast du 16 Byte genommen und nicht auch 15? |
Schreibfehler. Im Original ist es octet[16]
Falls interessant: Bei der ZV ist er bei folgendem Befehl:
Quelltext 1:
| imul eax,dword ptr [ebp+$00],$78 |
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 21.08.07 12:06
Dann hast Du dein Stackframe zerkloppt...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Di 21.08.07 21:45
Aber was mach ich denn anders als das Original? 
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
OlafSt
      
Beiträge: 486
Erhaltene Danke: 99
Win7, Win81, Win10
Tokyo, VS2017
|
Verfasst: Mi 22.08.07 11:35
Ein zerfledderter Stackframe ist eigentlich ein Hinweis darauf, das die Move-Operationen ein oder mehrere Bytes zuviel moven - und dabei Rücksprungadressen zerlegen.
_________________ Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 22.08.07 13:43
Das scheint ja das Problem zu sein, weil ich 3x move verwende, also 6 Byte schreiben will, aber nur 4 Byte habe. Aber genau so macht es der Original-Source in C++ ja auch und da funktioniert das 3x schreiben. Wird da eventuell die Variable automatisch vergrößert auf 6 Byte?
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
TGLDX
      
Beiträge: 22
|
Verfasst: Mi 22.08.07 13:53
Das Problem ist vermutlich, dass du move statt copymemory(was ja die Delphi-Version von memcpy ist) verwendest.
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 22.08.07 13:57
Hab gelesen, dass Move = memcpy entspricht, siehe:
www.delphipraxis.net/topic22956.html
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
TGLDX
      
Beiträge: 22
|
Verfasst: Mi 22.08.07 14:01
Du verwendest Move aber mit Zeigern!
Wenn dann solltest du die Parameter dereferenzieren, da du sonst nicht die Speicherstelle, sondern den Zeiger überschreibst.
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 22.08.07 14:09
Also so?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| class function encode16(Buf: PChar; Data: UInt16): PChar; var nData: UInt16; begin nData := htons(Data); Move(nData, Buf^, SizeOf(UInt16)); Result := Buf + SizeOf(UInt16); end;
class function encode(Buf: PChar; const Data: PChar; aLength: Cardinal): PChar; begin Move(Data, Buf^, aLength); Result := Buf + aLength; end; |
Die ZV bleibt, allerdings flieg ich nicht mehr aus dem Programm raus (also das Assembler-Fenster bleibt zu) und die ZV kommt nun an der markieren Stelle.
EDIT:
Ich habe den Zirkumflex nach Data entfernt, nun bleibt die ZV aus. Ist der Source nun soweit richtig?
EDIT2:
Mal eben mit Ethereal die Daten geprüft. In beiden Fällen (C++ und Delphi) sind die 28 Bytes groß, aber der Inhalt ist unerschiedlich. Es beginnt schon bei den ersten beiden Bytes, also:
Delphi-Quelltext 1:
| Ptr := encode16(Ptr, Msg.msgHdr.msgType); |
In der C++-Variante kommt da 00-01 raus (0x0001, weil Type = 1), aber in der Delphi-Variante 6e-cd.
EDIT3:
Da kommt immer 6e-cd raus, egal was ich für einen Typ da rein schreibe. Vielleicht liegt das Problem wo anders?
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
GTA-Place 
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Do 23.08.07 15:24
Bingo! Hier fehlte ein Zirkumflex:
Delphi-Quelltext 1:
| S := sendto(FD, Msg^, Len, 0, aTo, toLen); |
Jetzt erkennt Ethereal auch das Protokoll, das bringt mich schon einen ganzen Schritt weiter.
Danke für eure Hilfe!
EDIT: Das PChar(Octet[0]) scheint noch immer nicht korrekt zu sein, da kommt auf jedenfall was anderes raus als gewünscht. Irgendwelche Ideen?
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
tommie-lie
      
Beiträge: 4373
Ubuntu 7.10 "Gutsy Gibbon"
|
Verfasst: Do 23.08.07 17:16
GTA-Place hat folgendes geschrieben: | | EDIT: Das PChar(Octet[0]) scheint noch immer nicht korrekt zu sein, da kommt auf jedenfall was anderes raus als gewünscht. Irgendwelche Ideen? |
Weiter oben schrob ich " PChar(@Octet[0]).
Wenn du ein unsigned char octet[16] hast, dann wird ein Speicherbereich allokiert, der 16 unsigned char (16 Byte) umfasst und octet ist ein Pointer auf das erste unsigned char von diesen 16. Die Übersetzung nach Delphi, die dem entspricht ist also "@octet[0]", da Delphi keine Aussage darüber trifft, wie ein Array implementiert ist (und weil Compiler Magic existiert). Der anschließende reinterpret_cast<char *>() ist dann nichts anderes als ein PChar(@octet[0]).
Ob und wie das dann mit deiner Verwendung von Move() zusammenpasst, weiß ich aber nicht, ich habe keinen DCC und auch keine Befehlsreferenz zu Delphi.
_________________ Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
|
|
|