IsBadCodePtr
IsBadHugeReadPtr
IsBadHugeWritePtr
IsBadReadPtr
IsBadStringPtr
IsBadWritePtr
//下面的例子为什么测试错误?
procedure TForm1.Button1Click(Sender: TObject);
var
TB: TForm;
begin
TB := TForm.Create(nil);
// Form2.Show;
TB.Free;
if not IsBadCodePtr(TB) and (PPointer(TB)^ = Pointer(TForm)) then
begin
//应该是内存不存在了啊,怎么还会执行到这里?
TB.Free;
end;
end;
谢谢各位大哥,希望能帮我下这几个API究竟是怎么样的,我要判断一个对象或者内存有没有创建请问怎么来判断呢?
IsBadHugeReadPtr
IsBadHugeWritePtr
IsBadReadPtr
IsBadStringPtr
IsBadWritePtr
//下面的例子为什么测试错误?
procedure TForm1.Button1Click(Sender: TObject);
var
TB: TForm;
begin
TB := TForm.Create(nil);
// Form2.Show;
TB.Free;
if not IsBadCodePtr(TB) and (PPointer(TB)^ = Pointer(TForm)) then
begin
//应该是内存不存在了啊,怎么还会执行到这里?
TB.Free;
end;
end;
谢谢各位大哥,希望能帮我下这几个API究竟是怎么样的,我要判断一个对象或者内存有没有创建请问怎么来判断呢?
Free后赋值nil使用前
if tb=nil then
tb := TFrom.Create(nil);
而TB内容含有指向TForm类所在地址,所以后者也成立
var
TB: TForm;
begin
TB := TForm.Create(nil);
// Form2.Show;
FreeAndNil(TB);
if Assigned(TB) then
begin
TB.Free;
end;
end;
我的因为是网络程序,多个socket管理一个客户,偶尔网络不稳定的时候系统探测scoekt断开的时间不一致,所以我的不能想楼上各位人那么说,复制为nil来判断,因为第一个socket创建的对象(连接断开的时候会释放),第二个socket会用到,第二个socket收到网络信息(对象地址)需要判断下内存是否可用。
楼上谢谢您的freeandnil其实就是free然后:=nil;、这个我的程序类型不能这么用的
我不想用异常捕获的方法来试探一个地址内存对象是否正常因为我的程序都不用一句异常捕获的。能有判断的方法当然最好。
所以我需知道有什么方法可判断一个内存指针指向的地址是否可用
begin
pMemberClass := TOtherClassType.Create;
pMemberClass.Assign(aMemberClass);
//pMemberClass := aMemberClass;
end;
——
既然其它socket要用,为什么要在断开连接时释放?该对象为何不能设计为全局的或单例模式?
Form1.Free
执行之后,该内存区域很可能压根就没被交给Windows,而是留下来,供后面的程序继续使用,这个时候就不好判断该内存区域了,内存区域还能访问,以上函数都没得效果的。想其他办法
释放时,也要维护这个list。最好将此list管理类,设计为单例。
执行之后,该内存区域很可能压根就没被交给Windows,而是留下来,给你看个例子procedure TForm1.Button3Click(Sender: TObject);
var
OBJ : TComponent;
begin
Obj := TComponent.Create(NIL);
Obj.Tag := 1;
Obj.Free;
Caption := IntToStr(Obj.Tag);
end;程序会出错吗?多数时候不会出错,
而且执行之后Caption='1'
Delphi程序有自己的内存管理机制,他接管了这部分,供其他地方使用,
if Assigned(TB) then
...
unit HookClassDestroyByCheck;interfaceUses
Windows;//返回True时,Obj已经执行Free或者Obj地址无效, 返回False未执行Free
Function CheckObjectIsFreeed(Obj : TObject) : Boolean; assembler;implementation{$IFDEF VER150} // Delphi 7.0 已经验证通过
{$ELSE}
{$IFDEF VER210} // Delphi 2010 已经验证通过
{$ELSE}
{$MESSAGE '本单元提供的功能与Delphi版本密切相关,当前Delphi版本未验证.请验证后再使用.'}
{$ENDIF}
{$ENDIF}//返回True时,Obj已经执行Free或者Obj地址无效, 返回False未执行Free
Function CheckObjectIsFreeed(Obj : TObject) : Boolean; assembler;
asm
PUSH 1
PUSH EAX
PUSH 4
PUSH EAX
CALL IsBadReadPtr
TEST EAX , EAX
JNZ @@Exit
MOV EAX , [ESP]
PUSH 4
PUSH DWORD PTR [EAX] //ClassPointer ->> [ESP]
ADD DWORD PTR [ESP] , vmtSelfPtr;
CALL IsBadReadPtr;
TEST EAX , EAX;
JNZ @@Exit
MOV EAX , [ESP]
MOV EAX , [EAX]
CMP EAX , [EAX+vmtSelfPtr]
JNZ @@Exit
MOV [ESP+4] , 0
@@Exit:
POP EAX
POP EAX;
end;//验证版本,就是看一下System._ClassDestroy的代码是否和这个函数一样
procedure _OldClassDestroy(Instance: TObject);
begin
Instance.FreeInstance;
end;procedure NewClassDestroy(Instance: TObject);assembler;
asm
PUSH EAX;
PUSH 4;
PUSH EAX;
CALL _OldClassDestroy;
CALL IsBadWritePtr;
TEST EAX , EAX;
JNZ @@Exit
MOV EAX , [ESP]
PUSH 4
PUSH DWORD PTR [EAX] //ClassPointer ->> [ESP]
ADD DWORD PTR [ESP] , vmtSelfPtr;
CALL IsBadReadPtr;
TEST EAX , EAX;
JNZ @@Exit
MOV EAX , [ESP]
MOV EAX , [EAX]
CMP EAX , [EAX+vmtSelfPtr]
JNZ @@Exit
MOV EAX , [ESP]
MOV DWORD PTR [EAX] , 0;
@@Exit:
ADD ESP , 4;
end;procedure UnitInit;
var
Buf : Array [0..5] of Byte;
P : Pointer;
begin
Buf[0] := $68; //PUSH
PDWORD(@Buf[1])^ := DWORD(@NewClassDestroy); //Adr
Buf[5] := $C3; //Ret
asm
LEA EAX , System.@ClassDestroy;
MOV P , EAX;
end;
WriteProcessMemory(Windows.GetCurrentProcess() , P , @Buf , 5 , PDWORD(NIL)^);
end;initialization
UnitInit;
end.
如果按楼主前面的做法,对象变量是在方法里声明,也就是局部变量。那么此方法是否还有效呢?这个地方值得怀疑。