![]() |
Record als Konstantenobjekt nach Update D2009->Delphi XE
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:
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.
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; Herzlichen Dank, Jan |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
Mal mit ohne with versucht?
|
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
ParametersOfFit1 ist als property nur "read" deklariert, FParametersOfFit1 verwenden.
|
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
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:
Delphi-Quellcode:
... 0?
Copy (_Name, 0, NameLen-1);
Zitat:
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. :warn: |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
Zitat:
Zitat:
Report No: 56893 (RAID: 257191) Status: Closed with <> ".": Syntax ambiguity?! ![]() Zitat:
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 |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
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. :roll: Dieser Code
Delphi-Quellcode:
macht nun Folgendes:
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
Delphi-Quellcode:
(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)
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); 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. :angle2: PSS: Das selbe Problem hat übrigens auch die generische TList. :wall: (vielleicht lade ich dazu ja irgendwannl meinen "Bugfix" hoch) |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
Zitat:
Delphi-Quellcode:
Der Code beim ShowMessage ist identisch mit:
TMyClass=class(TObject)
private fMyRecord: TMyRecord; public property MyRecord: TMyRecord read fMyRecord; end; [...] ShowMessage(MyClassInstance.MyRecord.Value);
Delphi-Quellcode:
Wäre ja schlimm der Zugriff auf eine Variable Länger dauert nur weil man den Scope oder dergleichen einschränkt.
TMyClass=class(TObject)
public MyRecord: TMyRecord; end; [...] ShowMessage(MyClassInstance.MyRecord.Value); |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
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. :angle: |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
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:
Hier sollte klar sein das folgendes nicht geht da die Verknüpfung von TMyREcord.Val mit fVal1 fehlt.
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;
Delphi-Quellcode:
MyObjectInstance.MyRecord.Val1:=Irgendwas;
Zitat:
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. |
AW: Record als Konstantenobjekt nach Update D2009->Delphi XE
"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. :angle2: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz