Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Verstehe das Verhalten der Records nicht. (https://www.delphipraxis.net/194543-verstehe-das-verhalten-der-records-nicht.html)

DevLinus 6. Dez 2017 07:31

Verstehe das Verhalten der Records nicht.
 
Hallo zusammen,
geben ist Folgender Quellcode. An der Stelle wo CompareMem aufgerufen wird müssten die Records eigentlich Identisch sein. Die Methode gibt mir aber False zurück. Wenn ich die beiden Records auswerte scheinen alle Records gleich zu sein und KFMKey ist = 'XXX 148060'.

Nach dem ich es ein paar mal Debuggt habe, entschloss ich mich die Daten in eine Datei zu schreiben um zu prüfen ob die Binär gleich sind. Das Ergebniss ist das in der Datei jeweils der erste Wert steht und nicht der Neue. Dann habe ich noch folgende beiden Zeilen hinzugefügt und in der Datei wird es als XXX Test6001 gepseichert.
Code:
  lRec.SampleRecordInside.KfmKey := 'XXX 14806001';
  lRec.SampleRecordInside.KfmKey := 'XXX Test';
Muss ich die Record Felder Fillcharn? Ist dies das normale Verhalten? Wie Säubere ich das Recordfeld?

Code:
 
  TKFMKey = string[16];

  TSampleRecord = record
    Count : byte;
    KfmKey : TKFMKey;
  end;


  TOtherSampleRecord = record
    Count : byte;
    PaIsolatorKey : TKFMKey;
    PtIsolatorKey : TKFMKey;
  end;

  TMyRec = record
    aBoolean : boolean;
    KfmKey : TKFMKey;
    OtherSampleRecord : array[1..5] of TOtherSampleRecord;
    SampleRecordInside : TSampleRecord;
    SampleRecordOutside : TSampleRecord;
    SampleRecordMiddle : TSampleRecord;
    res : array[1..50] of byte;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn2Click(Sender: TObject);
var
  lRec : TMyRec;
  lRec2 : TMyRec;
  lStream : TFileStream;
  lStream2: TFileStream;
begin
  FillChar(lRec, sizeof(TMyRec),0);
  FillChar(lRec2, sizeof(TMyRec),0);
  lRec.KfmKey := 'XXX 14806001';
  lRec2.KfmKey := 'XXX 14806002';
  lRec.KfmKey := 'XXX 148060';
  lRec2.KfmKey := 'XXX 148060';

  if CompareMem(@lRec, @lRec2,SizeOf(TMyRec)) then // Müssten gleich sein sind sie aber nicht
    ShowMessage('Juhu')
  else
    ShowMessage('Fuck');
  lRec.SampleRecordInside.KfmKey := 'XXX 14806001';
  lRec.SampleRecordInside.KfmKey := 'XXX Test';
  ShowMessage(lRec.KfmKey);
  ShowMessage(lRec2.KfmKey);

  // Speichern der Testeinträge
  lStream := TFileStream.Create('C:\temp\test1a.dat',fmCreate);
  lStream.WriteBuffer(lRec,SizeOF(TMyRec));
  lStream.Free;
  lStream2 := TFileStream.Create('C:\temp\test2a.dat',fmCreate);
  lStream2.WriteBuffer(lRec2,SizeOF(TMyRec));
  lStream2.Free;
end;
Gruß,
DevLinus

Stevie 6. Dez 2017 07:59

AW: Verstehe das Verhalten der Records nicht.
 
Das Problem ist CompareMem auf einen shortstring.

Beim Zuweisen eines shortstrings wird nicht der "Rest" geleert.

Beispiel:

Delphi-Quellcode:
var
  s: string[16];
  i: Integer;
begin
  s := 'XXX 14806001';
  s := 'XXX 148060';
  for i := 1 to 16 do
    Write(s[i]);
end.

DevLinus 6. Dez 2017 08:04

AW: Verstehe das Verhalten der Records nicht.
 
Zitat:

Zitat von Stevie (Beitrag 1388024)
Das Problem ist CompareMem auf einen shortstring.

Beim Zuweisen eines shortstrings wird nicht der "Rest" geleert.

Beispiel:

Delphi-Quellcode:
var
  s: string[16];
  i: Integer;
begin
  s := 'XXX 14806001';
  s := 'XXX 148060';
  for i := 1 to 16 do
    Write(s[i]);
end.

Habe ich mir schon fast gedacht, aber warum wird mir im Debugger wenn ich die Variable Auswerte der Wert nicht angezeigt? Also muss ich jeden Short String, wo ich einen Kürzen String reinpacke vorher Fillcharn?

Fritzew 6. Dez 2017 08:28

AW: Verstehe das Verhalten der Records nicht.
 
Zitat:

Habe ich mir schon fast gedacht, aber warum wird mir im Debugger wenn ich die Variable Auswerte der Wert nicht angezeigt? Also muss ich jeden Short String, wo ich einen Kürzen String reinpacke vorher Fillcharn?
Mach Dir eine Compare Function für die Records, mit CompareMem wirst Du in solchen Fällen immer auf die Nase fallen. Da spielt auch das Align eine Rolle.

Ausgehend von Align 4 (der default denke ich) sieht Dein Record im Speicher so aus:

Delphi-Quellcode:
TSampleRecord = record
    Count : byte;
    hidden : array[0..2] of byte; // Für das Align wird das vom Compiler eingebaut
    KfmKey : TKFMKey; // 17 byte
   hidden : array[0..2] of byte; // Für das Align wird das vom Compiler eingebaut
  end;
Kannst Du einfach mit sizeof(TSampleRecord) nachschauen. Habe es jetzt nicht getestet aber gehe davon aus das der Record 24 Byte gross ist.

jaenicke 6. Dez 2017 08:44

AW: Verstehe das Verhalten der Records nicht.
 
Ich würde dafür class operators benutzen:
Delphi-Quellcode:
TSampleRecord = record
    Count: byte;
    KfmKey: TKFMKey; // 17 byte
    class operator Equal(a: TSampleRecord; b: TSampleRecord): Boolean;
  end;

...

class operator TSampleRecord.Equal(a: TSampleRecord; b: TSampleRecord): Boolean;
begin
  Result := (a.Count = b.Count) and (a.KfmKey = b.KfmKey);
end;

...

var
  Test1, Test2: TSampleRecord;
begin
  ...
  if Test1 = Test2 then // einfach vergleichen
    ...

Stevie 6. Dez 2017 08:45

AW: Verstehe das Verhalten der Records nicht.
 
Zitat:

Zitat von DevLinus (Beitrag 1388026)
Also muss ich jeden Short String, wo ich einen Kürzen String reinpacke vorher Fillcharn?

Spontan würde ich sagen, das ist eine Möglichkeit.

Je nach verwendeter Delphi Version steht dir aber auch die Möglichkeit der Operatorüberladung zur Verfügung, wo du einfach Equals implementieren kannst, dann kannst du einfach schreiben:
Delphi-Quellcode:
if Rec = lRec2 then
Zitat:

Zitat von Fritzew (Beitrag 1388028)
Mach Dir eine Compare Function für die Records, mit CompareMem wirst Du in solchen Fällen immer auf die Nase fallen. Da spielt auch das Align eine Rolle.

Hatte ich auch zuerst überlegt, aber wenn initial FillChar genutzt wird, sollte das kein Problem darstellen, weil auch die "Lücken" genullt werden.

p80286 6. Dez 2017 09:13

AW: Verstehe das Verhalten der Records nicht.
 
Zitat:

Zitat von Stevie (Beitrag 1388031)
Hatte ich auch zuerst überlegt, aber wenn initial FillChar genutzt wird, sollte das kein Problem darstellen, weil auch die "Lücken" genullt werden.

Da wir die Delphi Version die der TE nutzt nicht kennen, ist das wohl der kleinste gemeinsame Nenner.

Gruß
K-H

DevLinus 6. Dez 2017 09:27

AW: Verstehe das Verhalten der Records nicht.
 
Danke! Mir haben eure Tipps weiter geholfen.

Delphi Version habe ich jetzt angegeben.

Dalai 6. Dez 2017 14:27

AW: Verstehe das Verhalten der Records nicht.
 
Zitat:

Zitat von Stevie (Beitrag 1388031)
Zitat:

Zitat von DevLinus (Beitrag 1388026)
Also muss ich jeden Short String, wo ich einen Kürzen String reinpacke vorher Fillcharn?

Spontan würde ich sagen, das ist eine Möglichkeit.

War es nicht so, dass es keine gute Idee ist, FillChar auf einen Record anzuwenden, in dem Strings enthalten sind, weil dadurch etwas kaputtgemacht wird (Referenzzählung oder so)?

Grüße
Dalai

Zacherl 6. Dez 2017 14:30

AW: Verstehe das Verhalten der Records nicht.
 
Bei ShortStrings geht das klar.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:19 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz