下面显示的两个程序尝试使用此处描述的技术测试对象是否被释放,对已释放的对象的错误引用.
如果在Delphi 7下编译,下面显示的第一个程序运行正确,但如果在Delphi XE和upper下编译,则错误地运行.也就是说,它输出
D7 DXE
True True
True True
True False
True True
False True
False False
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
function ValidateObj(Obj: TObject): Pointer;
// see { Virtual method table entries } in System.pas
begin
Result := Obj;
if Assigned(Result) then
try
if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then
// object not valid anymore
Result := nil;
except
Result := nil;
end;
end;
function ValidateObj2(Obj: TObject): Pointer;
type
PPVmt = ^PVmt;
PVmt = ^TVmt;
TVmt = record
SelfPtr : TClass;
Other : array[0..17] of pointer;
end;
var
Vmt: PVmt;
begin
Result := Obj;
if Assigned(Result) then
try
Vmt := PVmt(Obj.ClassType);
Dec(Vmt);
if Obj.ClassType <> Vmt.SelfPtr then
Result := nil;
except
Result := nil;
end;
end;
var
Obj: TObject;
begin
Obj := TObject.Create;
Writeln(BoolToStr(Assigned(Obj), True));
Writeln(BoolToStr(Assigned(ValidateObj(Obj)), True));
Writeln(BoolToStr(Assigned(ValidateObj2(Obj)), True));
Obj.free;
Writeln(BoolToStr(Assigned(Obj), True));
Writeln(BoolToStr(Assigned(ValidateObj(Obj)), True));
Writeln(BoolToStr(Assigned(ValidateObj2(Obj)), True));
Readln;
end.
Run Code Online (Sandbox Code Playgroud)
第二个程序,显式使用FastMM4,如下所示,在Delphi 7或XE和upper下编译时运行错误.也就是说,它输出
Expected D7 DXE
False False False
True True True
True True True
True True False
True False False
True True True
False True True
False True False
program Project2;
{$APPTYPE CONSOLE}
uses
FastMM4,
SysUtils;
function ValidateObj(Obj: TObject): Pointer;
// see { Virtual method table entries } in System.pas
begin
Result := Obj;
if Assigned(Result) then
try
if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then
// object not valid anymore
Result := nil;
except
Result := nil;
end;
end;
function ValidateObj2(Obj: TObject): Pointer;
type
PPVmt = ^PVmt;
PVmt = ^TVmt;
TVmt = record
SelfPtr : TClass;
Other : array[0..17] of pointer;
end;
var
Vmt: PVmt;
begin
Result := Obj;
if Assigned(Result) then
try
Vmt := PVmt(Obj.ClassType);
Dec(Vmt);
if Obj.ClassType <> Vmt.SelfPtr then
Result := nil;
except
Result := nil;
end;
end;
var
Obj: TObject;
begin
Obj := TObject.Create;
Writeln(BoolToStr(Obj is FastMM4.TFreedObject, True));
Writeln(BoolToStr(Assigned(Obj), True));
Writeln(BoolToStr(Assigned(ValidateObj(Obj)), True));
Writeln(BoolToStr(Assigned(ValidateObj2(Obj)), True));
Obj.free;
Writeln(BoolToStr(Obj is FastMM4.TFreedObject, True));
Writeln(BoolToStr(Assigned(Obj), True));
Writeln(BoolToStr(Assigned(ValidateObj(Obj)), True));
Writeln(BoolToStr(Assigned(ValidateObj2(Obj)), True));
Readln;
end.
Run Code Online (Sandbox Code Playgroud)
我很困惑如何导致错误的行为,并想知道如何测试一个对象是否被释放为Delphi 7和Delphi XE和鞋面,特别是当使用FastMM4时?