![]() |
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
.Free wird niemal den Objektzeiger NILen, denn Methoden verändern nie den Objektzeiger und das ist auh gut so.
Einzig und alleine der Constructor macht das indirekt, aber nur weil dafür eine Zuweisung ( := ) verwendet wird. FreeAndNil greift direkt auf den Objektzeiger (die Variable) zu und kann so deren Inhal ändern. PS: Wenn jedes Free den Objektzeiger ändern könnte/würde, dann würde es hier Probleme geben.
Delphi-Quellcode:
procedure Test(const Obj: TObject);
begin obj.Free; end; Zitat:
- .Free ist eine Methode - Methoden ändern niemal Objektvariablen - und ich weiß nicht warum sich jemand sowas wirklich wünschen würde? Immerhin gibt es hierfür FreeAndNil und da weiß man genau was es macht. .Free gibt nur das Objekt frei und macht sonst nichts. |
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Ich möchte die Diskussion nicht ausufern lassen, aber kurz noch Folgendes:
Zitat:
Zitat:
BTW: Ich kann mich an eine Sprache namens Clipper erinnern, mit der man vor 20 Jahren so etwas per Preprozessordirektive leicht lösen konnte. Zitat:
|
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Prüft nicht Assigned intern nur auf NIL?
Denn einen Zeiger mit einer Adresse im Bauch, kann man nicht ansehen ob der Zeiger noch gültig ist oder nicht. Daher die NIL Geschichte. |
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Zitat:
Schon könnte man hier das Objekt nicht mehr "ordentlich" freigeben. :stupid: Egal ob man es über einen Compilerschalter an- oder ausstellen kann ... sowas wird ja global gesetzt und ein lokaler Compilerschalter ist Schwachsinn, denn da kann man auch gleich FreeAndNil verwenden, welches ich dann übersichtlicher/verständlicher finde. PS: C# ist was anderes, denn dort arbeitet auch ein GarbageCollector und es gibt insgesamt einen anderes Speichermanagement. Dort gibt es quasi keine Objekte, sondern eigentlich nur sowas wie Interfaces und der Speichermanager hat die volle Kontrolle über die ganzen Zeiger, bzw. er muß sogar die Kontrolle haben, sonst geht sowas garnicht. Zitat:
Wie gesagt, wenn man auf die interne Struktur schaut, dann kann das nix werden, denn - entweder liegt an der Stelle irgendwas, welches zufällig so aussueht, wie das auf welches man prüfen will - oder es liegt inzwischen ein anderes Objekt dort. (siehe nachfolgender Code) Bsp:
Delphi-Quellcode:
var ObjA, ObjB: TMyObject;
ObjA := TMyObject.Create; ObjA.Free; ObjB := TMyObject.Create; if ObjektAssigned(ObjA) then // wenn jetzt zufällig der Speicher des Objekts B an der selben Stelle liegt, // wo vorher das Objekt A lag, dann würde ObjektAssigned an dieser Stelle // natürlich ein Objekt vorfinden (und zwar das aus ObjB) und würde demnach // korrekter Weise TRUE liefern, obwohl in ObjA eigentlich kein Objekt mehr drin ist.
Delphi-Quellcode:
program Project3;
uses Windows; type TString20 = String[20]; TStrObject = class private FStr: TString20; public constructor Create(const S: TString20); property Str: TString20 read FStr; End; constructor TStrObject.Create(const S: TString20); begin FillChar(FStr, SizeOf(FStr), 0); FStr := S; end; var ObjA, ObjB: TStrObject; begin ObjA := TStrObject.Create('Ich bin A.'); ObjA.Free; ObjB := TStrObject.Create('Ich aber bin B?'); MessageBoxA(0, PAnsiChar(@ObjA.Str[1]), nil, 0); if ObjA = ObjB then ; end. ObjA sagt: Ich aber bin B?
Delphi-Quellcode:
program Project3;
uses Windows; type TString20 = String[20]; TStrObject = class private FStr: TString20; public constructor Create(const S: TString20); property Str: TString20 read FStr; End; constructor TStrObject.Create(const S: TString20); begin FillChar(FStr, SizeOf(FStr), 0); // nur wegen der #0 hinter dem String FStr := S; end; var ObjA, ObjB: TStrObject; begin ObjA := TStrObject.Create('Ich bin A.'); FreeAndNil(ObjA); ObjB := TStrObject.Create('Ich bin B.'); if Assigned(ObjA) then MessageBoxA(0, PAnsiChar(@ObjA.Str[1]), nil, 0) else MessageBoxA(0, 'ObjA existiert nicht.', nil, 0); if ObjA = ObjB then ; // für's Debugging end. ObjA sagt: ObjA existiert nicht.
Delphi-Quellcode:
program Project3;
uses Windows, SysUtils; type TString20 = String[20]; TStrObject = class private FStr: TString20; public constructor Create(const S: TString20); property Str: TString20 read FStr; End; constructor TStrObject.Create(const S: TString20); begin FillChar(FStr, SizeOf(FStr), 0); // nur wegen der #0 hinter dem String FStr := S; end; function IsValidObject(aObject: TObject): Boolean; type PVmt = ^TVmt; TVmt = packed record SelfPtr: TClass; ignored: array [0..-(4 + vmtSelfPtr) - 1] of Byte; end; var VMT: PVmt; begin Result := False; if IsBadReadPtr(aObject, 4) then Exit; VMT := PVmt(aObject.ClassType); Dec(VMT); if IsBadReadPtr(VMT, 4) then Exit; if aObject.ClassType = VMT.SelfPtr then Result := True; end; var ObjA, ObjB: TStrObject; begin ObjA := TStrObject.Create('Ich bin A.'); ObjA.Free; ObjB := TStrObject.Create('Ha, ich bin B.'); if IsValidObject(ObjA) then MessageBoxA(0, PAnsiChar(@ObjA.Str[1]), nil, 0) else MessageBoxA(0, 'ObjA existiert nicht.', nil, 0); if ObjA = ObjB then ; // für's Debugging end. ObjA sagt: Ha, ich bin B.
Delphi-Quellcode:
program Project3;
uses Windows, SysUtils; type TString30 = String[30]; TStrObject = class private FStr: TString30; public constructor Create(const S: TString30); property Str: TString30 read FStr; End; constructor TStrObject.Create(const S: TString30); begin FillChar(FStr, SizeOf(FStr), 0); // nur wegen der #0 hinter dem String FStr := S; end; function IsValidObject(aObject: TObject): Boolean; type PVmt = ^TVmt; TVmt = packed record SelfPtr: TClass; ignored: array [0..-(4 + vmtSelfPtr) - 1] of Byte; end; var VMT: PVmt; begin Result := False; if IsBadReadPtr(aObject, 4) then Exit; VMT := PVmt(aObject.ClassType); Dec(VMT); if IsBadReadPtr(VMT, 4) then Exit; if aObject.ClassType = VMT.SelfPtr then Result := True; end; var ObjA: TStrObject; begin ObjA := TStrObject.Create('Huch, was ist denn das hier?'); ObjA.Free; if IsValidObject(ObjA) then MessageBoxA(0, PAnsiChar(@ObjA.Str[1]), nil, 0) else MessageBoxA(0, 'ObjA existiert nicht.', nil, 0); if ObjA = nil then ; // für's Debugging end. ObjA sagt: Huch, was ist denn das hier?
Delphi-Quellcode:
program Project3;
uses Windows, SysUtils; type TString20 = String[20]; TStrObject = class private FStr: TString20; public constructor Create(const S: TString20); property Str: TString20 read FStr; End; constructor TStrObject.Create(const S: TString20); begin FillChar(FStr, SizeOf(FStr), 0); // nur wegen der #0 hinter dem String FStr := S; end; var ObjA, ObjB: TStrObject; begin ObjA := TStrObject.Create('Ich bin A.'); FreeAndNil(ObjA); ObjB := TStrObject.Create('Ich bin B.'); if Assigned(ObjA) then MessageBoxA(0, PAnsiChar(@ObjA.Str[1]), nil, 0) else MessageBoxA(0, 'Ich existiere nicht.', nil, 0); if ObjA = ObjB then ; // für's Debugging end. ObjA sagt: Ich existiere nicht. Zitat:
In Delphi liegt die Kontrole über den Speicher beim Programmierer (abgrsehn einige bestimmter Typen, wie Strings und dyn. Arrays) und via .Free und FreeAndNil hat er die Kontrolle darüber was gemacht werden soll ...... er muß es nur ordentlich nutzen. |
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Zwar leicht OT, aber das ist einer der Gründe, warum ich .NET mittlerweile voll gerne mag. Foo = null; und der GC kümmert sich um den Rest, heile Welt ohne Krämpfe.
Ich vermute auch, dass der Schwenk hin zu managed Umgebungen seinen Teil dazu beiträgt, dass dieser Problematik bei den IDE/Sprach-Entwicklern weithin eher wenig Bedeutung mehr angerechnet wird. (Davon ab halte ich hier auch FreeAndNil() für den geeignetesten Weg, der auch eigentlich immer klappen sollte. Es sei denn, ihr verhackstückt da regelrecht kriminelle Dinge, und dann ist's eh wurscht :P) |
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Zitat:
|
Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010
Wer tut das schon? :angel2: (Ich, zumindest mit diesem als alleinigen Grund, sicherlich nicht. Dafür ist mir FreeAndNil() im Vergleich wieder zu einfach anwendbar :stupid: )
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:43 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