AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Record als Konstantenobjekt nach Update D2009->Delphi XE

Record als Konstantenobjekt nach Update D2009->Delphi XE

Ein Thema von BoolString · begonnen am 30. Aug 2011 · letzter Beitrag vom 31. Aug 2011
Antwort Antwort
Seite 1 von 2  1 2   
BoolString

Registriert seit: 2. Feb 2009
Ort: Varel
70 Beiträge
 
RAD-Studio 2009 Pro
 
#1

Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 16:58
Schönenn guten Abend,

ich habe gerade ein Update von Delphi 2009 auf Delphi XE durchgeführt. Beim Start eines Projektes, durfte ich feststellen, daß eine alte Unit nicht mehr funktioniert.

Mir ist derzeit nicht ganz klar, wo der Fehler liegt. Vielleicht kann mir hier jemand einen Tipp geben. Ich bekomme die Fehlermeldung, daß ich hier ein jetzt Konstantenobjekt habe und als Folgefehler daraus die Meldung, daß nichts zugewiesen werden kann. Möglicherweise liegt es an einigen Veränderungen zwischen D2009->DXE.

Ich hoffe ich habe hier alle relevanten Teile für eine Beispielprozedur rauskopiert.

Delphi-Quellcode:
unit uFLPReader;

interface

uses
  Windows, Classes, SysUtils;



type
 TAlgenklassenparameter = packed record
    _Name: AnsiString;
    _FlagUseInFit: Longint;
    _Fingerprint_Standardabweichung: array[1..16] of Double;
    _LEDOffset: Double;
  end;

  TParametersOfFit1 = packed record
    _Algenklassenparameter: array[1..8] of TAlgenklassenparameter;
  end;



 TFLPModule = class(TObject)
  private
    FParametersOfFit1: TParametersOfFit1;
    procedure ReadParametersOfFit1(const AStream: TStream);
public
    property ParametersOfFit1: TParametersOfFit1 read FParametersOfFit1;
end;

implementation

procedure TFLPModule.ReadParametersOfFit1( const AStream: TStream);
var
  i : Integer;
  NameLen : Longint;
  Dummy : AnsiString;
begin
  for i := 1 to 8 do
    with ParametersOfFit1._Algenklassenparameter[i] do
    begin
      AStream.ReadBuffer(NameLen, SizeOf(NameLen));
      SetLength (_Name, NameLen); // hier ein Fehler
      if NameLen > 0 then
      Begin
        AStream.ReadBuffer(_Name[1], NameLen); // hier ein Fehler
        _Name := Copy (_Name, 0, NameLen-1);
      end
      Else
      Begin
        _Name := '';
      end;
      AStream.ReadBuffer(_FlagUseInFit, SizeOf(_FlagUseInFit)); // hier ein Fehler
      AStream.ReadBuffer(_Fingerprint_Standardabweichung, SizeOf(_Fingerprint_Standardabweichung)); // hier ein Fehler
      AStream.ReadBuffer(_LEDOffset, SizeOf(_LEDOffset)); // hier ein Fehler
    end;
end;
Analog gibt es noch andere Stellen, wo der Fehler meiner Meinung nach aber die selbe Ursache haben dürfte. Bisher habe ich mit dieser Unit nie Probleme gehabt. Ich schleppe sie seit D7 in einem Projekt mit durch. Möglicherweise bin ich gerade mit Blindheit geschlagen, aber ich komm nicht drauf.


Herzlichen Dank,

Jan
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.830 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 17:02
Mal mit ohne with versucht?
Markus Kinzler
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.395 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 17:11
ParametersOfFit1 ist als property nur "read" deklariert, FParametersOfFit1 verwenden.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 17:12
In 2010/XE gab es ein paar Änderungen bezüglich der Zugriffsprüfungen von Const-Parametern und anderen Konstanten.

Kann schon sein, daß sich da ein Bug versteckt hat.


PS: Copy (_Name, 0, NameLen-1); ... 0?


Zitat:
ParametersOfFit1 ist als property nur "read" deklariert, FParametersOfFit1 verwenden.
Stimmt, also ist diese Meldung wohl richtig
und der Code hätte nie funktionieren dürfen, da man die Inhalte von Record-Parametern nicht ändern kann, es sei denn man weist einen kompletten Record zu.
Änderungen an einzelnen Feldern werden nur an der Kopie des Property vorgenommen und nicht an dem, worauf das Property zeigt ... darum diese Meldung.

[edit] durch die Codeoptimierung funktionierte es zufällig doch mal



Du mußt dort auf FParametersOfFit1 zugreifen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list

Geändert von himitsu (30. Aug 2011 um 18:50 Uhr)
  Mit Zitat antworten Zitat
USchuster

Registriert seit: 12. Sep 2010
Ort: L.E.
120 Beiträge
 
Delphi XE3 Professional
 
#5

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 17:49
In 2010/XE gab es ein paar Änderungen bezüglich der Zugriffsprüfungen von Const-Parametern und anderen Konstanten.
Die Änderungen gab es in D2010.

Zitat:
ParametersOfFit1 ist als property nur "read" deklariert, FParametersOfFit1 verwenden.
Stimmt, also ist diese Meldung wohl richtig
und der Code hätte nie funktionieren dürfen,
Der dazugehörige Bug wurde in D2010 gefixed.

Report No: 56893 (RAID: 257191) Status: Closed
with <> ".": Syntax ambiguity?!
http://qc.embarcadero.com/wc/qcmain.aspx?d=56893

Änderungen an einzelnen Feldern werden nur an der Kopie des Property vorgenommen und nicht an dem, worauf das Property zeigt ... darum diese Meldung.
Und das konnte zu scheinbarem Datenverlust kommen, da nicht das passierte was der Programmierer wollte. Folgender Ausschnitt stammt aus einem Duplikat von QC 56893.

Delphi-Quellcode:
  with t.Items[0] do
  begin
    writeln(s); // str
    s := ':(';
    b := true;
    writeln(b); // true
  end;
  writeln(t.Items[0].s); // str <-- data loss
  writeln(t.Items[0].b); // false <-- data loss
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 18:11
Sobald lesend auf ein Property zugegriffen wird (also nicht Property := ...), wird READ verwendet, welches eine lokale Kopie des Wertes erstellt.
Alles was in dieser Kopie verändert wird, hat keinen Einfluß auf das Property.
[add] (bei direkten Zugriffen auf Felder ht es doch Einfluß, was aber so nicht erlaubt ist)

Darum wirft man hier nun auch endlich mal einen Compiler-Fehler.


Was aber leider auf Record-Methoden noch nicht zutrifft, da man diese nicht als "Konstant" deklarieren kann.
Ist schon witzig, wie man darüben dennoch eine Konstante verändern kann.

Dieser Code
Delphi-Quellcode:
with t.Item do
begin
  s := ':(';
  writeln(s); // str
  b := true;
  writeln(b); // true
end;
writeln(t.Item.s); // str <-- data loss
writeln(t.Item.b); // false <-- data loss
t.Item.s := ':)';
writeln(t.Item.s); // str <-- data loss
macht nun Folgendes:
Delphi-Quellcode:
Temp1 := t.Item; // t.Item {Getter}
begin
  Temp1.s := ':(';
  writeln(Temp1.s);
  Temp1.b := true;
  writeln(Temp1.b);
end;
Temp2 := t.Item;
writeln(Temp2.s);
Temp3 := t.Item;
writeln(Temp3.b);
Temp4 := t.Item;
Temp4.s := ':)';
Temp5 := t.Item;
writeln(Temp5.s);
(die Codeoptimierung ist natürlich so schlau möglichst nur eine Temp-Variable zu nutzen und diese überall wiederzuverwenden, was aber an den auszuführenden Befehlen nichts ändert)



Da Emba ja leider nicht von selber auf die Idee kommt, hier nachher die TempVar an den Setter zurück zu übergeben, muß man es manuell machen.
Delphi-Quellcode:
MyVar := t.Item; {Getter}
with MyVar do
begin
  s := ':(';
  writeln(s);
  b := true;
  writeln(b);
end;
t.Item := MyVar; {Setter}

writeln(t.Item.s); {Getter}
writeln(t.Item.b); {Getter}

MyVar := t.Item; {Getter}
MyVar.s := ':)';
t.Item := MyVar; {Setter}

writeln(t.Item.s); {Getter}



PS: Das trifft auch auf Objekte zu, genauer auf den Objektzeiger.
Den Objektinhalt kann man natürlich ändern, da er ja nicht in dieser Kopie enthalten ist.

PSS: Das selbe Problem hat übrigens auch die generische TList.
(vielleicht lade ich dazu ja irgendwannl meinen "Bugfix" hoch)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list

Geändert von himitsu (30. Aug 2011 um 18:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 18:37
Zitat:
Sobald lesend auf ein Property zugegriffen wird (also nicht Property := ...), wird READ verwendet, welches eine lokale Kopie des Wertes erstellt.
Das stimmt so nicht. Vielmehr dient read/write nur der Zugriffskontrolle zur Compilezeit. Beim ShowMessage wird hier intern (asm-code) keine Kopie von fMyRecord erstellt.
Delphi-Quellcode:
TMyClass=class(TObject)
private
  fMyRecord: TMyRecord;
public
  property MyRecord: TMyRecord read fMyRecord;
end;
[...]
ShowMessage(MyClassInstance.MyRecord.Value);
Der Code beim ShowMessage ist identisch mit:
Delphi-Quellcode:
TMyClass=class(TObject)
public
  MyRecord: TMyRecord;
end;
[...]
ShowMessage(MyClassInstance.MyRecord.Value);
Wäre ja schlimm der Zugriff auf eine Variable Länger dauert nur weil man den Scope oder dergleichen einschränkt.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 18:46
hmmmmm.

OK, wenn, dann aber nur, wenn direkt auf auf ein Feld zugegriffen wird.
Gut, so könnte es doch mal zufällig funktioniert haben. ( Codeoptimierung? )

Da aber theoretisch auch ein Getter möglich wäre, würde/dürfte es dennoch nicht gehn.
PS: Das ist/war natürlich auch ein "Sicherheitsloch", da es ja als "schreibgeschützt" deklariert war.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list

Geändert von himitsu (30. Aug 2011 um 18:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 18:56
Natürlich funktioniert das nur wenn auf ein Feld zugegriffen wird. Aber genau darum ging es hier.
Wenn man eine Funktion hat die etwas zurück liefert sollte klar sein das mit Änderung des Funktionsergebnisses nicht das geändert wird woraus das Funktionsergebnis zusammengesetzt wird. Dafür würde ja auch die Verknüpfung fehlen:
Delphi-Quellcode:
TMyObject = class(TObject)
private
  fVal1: Integer;
  fVal2: Integer;
  function GetValues(): TMyRecord;
public
  property MyRecord: TMyRecord read GetValues;
end;
[...]
function TMyObject.GetValues(): TMyRecord;
begin
  result.Val1:=fVal1;
  result.Val2:=fVal2;
end;
Hier sollte klar sein das folgendes nicht geht da die Verknüpfung von TMyREcord.Val mit fVal1 fehlt.
MyObjectInstance.MyRecord.Val1:=Irgendwas;
Zitat:
Gut, so könnte es doch mal zufällig funktioniert haben.
Nichts mit Zufall. Logik. Es macht überhaupt keinen Sinn eine Kopie zu erstellen da zur Compilezeit der erlaubte Zugriff fest steht.
Read und Write sind Schlüsselwörter um den Zugriff zu begrenzen ebenso wie private,protected etc.
[Edit]
Diese Schlüsselwörter dienen nicht dazu den Speicher zu verschlüsseln oder andere Stolpersteine zu erzeugen um zu verhindern das man den Speicher nutzen kann. Sie dienen einzig und allein dem Begrenzen des "normalen" Zugriffs über Properties etc.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's

Geändert von SirThornberry (30. Aug 2011 um 19:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
40.509 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Record als Konstantenobjekt nach Update D2009->Delphi XE

  Alt 30. Aug 2011, 19:06
"zufällig" im sinne von, daß hier zufällig kein Getter verwendet wurde.

Wäre ja großer Zufall, wenn hier damals wirklich so geplant wurde, daß diese Codeoptimierung ausgenutzt werden konnte.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf