Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#14

Re: Delphi 7 Hack für Assigned -> Ersatz für Delphi 2010

  Alt 23. Apr 2010, 10:30
Zitat von knochen:
Das würde dann wohl der Compiler verbieten,
Genau. Und jetzt stell dir mal vor das Free würde standardmäßig den Objektzeiger auf NIL setzen.
Schon könnte man hier das Objekt nicht mehr "ordentlich" freigeben.

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 von generic:
Prüft nicht Assigned intern nur auf NIL?
Genau.

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 von knochen:
Schlimm genung, denn das ist ja das Problem...
Ich sehe da kein Problem.
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.
$2B or not $2B
  Mit Zitat antworten Zitat