Autor Beitrag
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: So 19.08.07 10:47 
Moin,

ich hab hier ein Problem beim Beschreiben / Füllen eines Buffers:

ausblenden 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: So 19.08.07 11:42 
Uargh, wo grabt ihr eigentlich immer solchen C++-Code aus?

user profile iconGTA-Place hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
  Ptr := encode(Ptr, @Msg.msgHdr.msgId.Octet, SizeOf(Msg.msgHdr.msgId));					

[...]
ausblenden C#-Quelltext
1:
   ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));					
(Highligh von mir verändert)
Da ist ein semantischer Unterschied in deinem Delphi-Quelltext. Bei dir wird durch den @-Operator nicht etwa msg.msgHdr.id.octet kopiert, sondern die Adresse von msg.msgHdr.id.octet. Wenn sizeof(msg.msgHdr.msgID) > sizeof(Pointer) und wenn innerhalb dieses Bereiches im Adressbereich eine Allokierungslücke ist, gibt es eine AccessViolation, weil dein Prozess nicht wild unallokierten Speicher lesen darf.

_________________
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: So 19.08.07 12:09 
user profile iconGTA-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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mo 20.08.07 17:55 
Sehr spezifisches Problem, trotzdem mal *push* :lol:

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Mo 20.08.07 18:05 
user profile iconGTA-Place hat folgendes geschrieben:
Gehen tut folgendes:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Mo 20.08.07 18:47 
user profile iconGTA-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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mo 20.08.07 18:52 
Okay, das geht, aber die ZV bleibt.

user profile icontommie-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:
ausblenden Quelltext
1:
imul eax,dword ptr [ebp+$00],$78					

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Di 21.08.07 21:45 
Aber was mach ich denn anders als das Original? :nixweiss:

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 22



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 22



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mi 22.08.07 14:09 
Also so?

ausblenden 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);  // EDIT: ^ nach Data muss weg!
  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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Do 23.08.07 15:24 
Bingo! Hier fehlte ein Zirkumflex:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Do 23.08.07 17:16 
user profile iconGTA-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