type
//一个结构体
PSomeRecord =^TSomeRecord;
TSomeRecord = record
a:string;
end; //一个类
TSomeObject = class(TObject)
destructor destroy;override;
end;var
aValue:TObject;//存储指针的变量//执行以下代码
begin
//一种情况-------------------------------------
//如果给aValue赋值一个TObject的派生类
aValue := TSomeObject.Create;
//我就需要这样释放,正确调用了destroy方法
aValue.Free;
//另一种情况-------------------------------------
//给aValue赋值一个结构体变量
tmp := new(PSomeRecord);
tmp^.a := 'llllll'; aValue := Pointer(tmp);
//就需要这样来释放aValue
Dispose(Pointer(aValue));
end.我怎样才能在不知道aValue存储的指针指向的是TObject或是Struct的情况先,用统一的方式来释放aValue呢?不够分可以再加
//一个结构体
PSomeRecord =^TSomeRecord;
TSomeRecord = record
a:string;
end; //一个类
TSomeObject = class(TObject)
destructor destroy;override;
end;var
aValue:TObject;//存储指针的变量//执行以下代码
begin
//一种情况-------------------------------------
//如果给aValue赋值一个TObject的派生类
aValue := TSomeObject.Create;
//我就需要这样释放,正确调用了destroy方法
aValue.Free;
//另一种情况-------------------------------------
//给aValue赋值一个结构体变量
tmp := new(PSomeRecord);
tmp^.a := 'llllll'; aValue := Pointer(tmp);
//就需要这样来释放aValue
Dispose(Pointer(aValue));
end.我怎样才能在不知道aValue存储的指针指向的是TObject或是Struct的情况先,用统一的方式来释放aValue呢?不够分可以再加
解决方案 »
- 有多个ie进程时弹出ie窗口出现超时错误!!!!急!!!
- 如何实现文本转图片的处理?
- 在IdTCPServer1Execute处理中如何弹出多个模式窗口?
- 请猛禽接分 原帖http://expert.csdn.net/Expert/topic/2368/2368797.xml?temp=.1806757
- 高分求教Delphi窗体问题(详情请进)
- dxNavBar问题
- 这是不是delphi的bug?欢迎高手前来讨论!
- query数据库问题?调试了一星期无法通过,谁告诉我是为什么?
- ListView能否像StringGrid一样可编辑?
- 各位好,本人想找个老师,经常在线的,做delphi的,本人勤学向上,绝对不会给老师丢脸,有哪位乐于助人的,请找我联系,QQ:121483953
- 报表打印问题,请各位高手多指教!急!!
- 这个sql语句为什么不能执行呢?
例如
if isObject(aValue)之类的aValue is TObject 无法判断
是否可以通过vmtCreateObject之类的偏移来判断呢?
如果可以代码该如何写阿
看看aValue.a是否是字符串,......
//所有对象指针的前4个字节都用来保存该对象的类地址~~type
PSomeRecord =^TSomeRecord;
TSomeRecord = record
a:string;
end; TSomeObject = class(TObject)
end;procedure FreeValue(mValue: TObject);
begin
if mValue = nil then Exit;
if PPointer(mValue)^ = TSomeObject then //mValue为TSomeObject对象
TSomeObject(mValue).Free
else Dispose(PSomeRecord(mValue));
end;procedure TForm1.Button1Click(Sender: TObject);
var
aValue: TObject;
begin
aValue := TSomeObject.Create;
FreeValue(aValue);
New(PSomeRecord(aValue));
PSomeRecord(aValue)^.a := 'llllll';
FreeValue(aValue);
end;
var s:string;
begin
try
result:=TObject(p).ClassName<>'';
except
result:=false;
end;
end;
的答案要异常,如果P指向一个结构体的化
zswang(伴水清清)(专家门诊清洁工):
你的答案我能够理解,但是还不是我想要的,我的意思是对于调用者并不知道存入的具体类型是什么,只能确定存入的不是TObject就是Struct,而跟具体的TSomeObject无关,
因为,我完全可以使用TObject(aValue).Free来释放aValue(如果是TObject的化)或者Dispose(Pointer(aValue))来释放record指针,而没有内存泄漏,因此答案还未得到的说。
我在TypInfo中找到了一些仿佛有用的东西
可以使用pTypeInfo(TypeInfo(TSomeObject)).Kind来得到类型的信息
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,
tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray);
但是遗憾的是必须传入的参数是类型信息,而不能传入一个变量进去,继续期待ing...
var vmt:Pointer;
NameAddress:Integer;
begin
Result:=false;
if(IsBadReadPtr(p,4))then exit;
vmt:=PPointer(p)^;
if(IsBadReadPtr(vmt,4))then exit;
NameAddress:=Integer(vmt) + vmtClassName;
if(IsBadReadPtr(Pointer(NameAddress),4))then exit;
Result:=lstrlen(PPointer(NameAddress)^)<>0;
end;
PSomeRecord =^TSomeRecord;
TSomeRecord = record
a:string;
end;function IsClass(mPointer: Pointer): Boolean;
var
vClassName: PShortString;
begin
Result := False;
if IsBadReadPtr(mPointer, 4)then exit;
vClassName := PPointer(Integer(mPointer) + vmtClassName)^;
if IsBadReadPtr(vClassName, 4) then Exit;
Result := IsValidIdent(vClassName^);
end;function IsObject(mPointer: Pointer): Boolean;
begin
Result := IsClass(PPointer(mPointer)^);
end;procedure FreeValue(mValue: TObject);
begin
if mValue = nil then Exit;
if IsObject(mValue) then //mValue为TObject对象
TObject(mValue).Free
else Dispose(PSomeRecord(mValue));
end;procedure TForm1.Button1Click(Sender: TObject);
var
aValue: TObject;
begin
aValue := TObject.Create;
FreeValue(aValue);
New(PSomeRecord(aValue));
PSomeRecord(aValue)^.a := 'llllll';
FreeValue(aValue);
end;
begin
if mValue = nil then Exit;
if IsObject(mValue) then //mValue为TObject对象
TObject(mValue).Free
else Dispose(PSomeRecord(mValue));
end;
的最后一句改成
else Dispose(Pointer(mValue));
能正确释放吗?
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
P: Pointer;
begin
for I := 0 to 1024 * 1024 do
begin
New(PString(P));
PString(P)^ := '我爱北京天安门!';
// Dispose(PString(P)); //没有内存泄漏
Dispose(P); //大量内存泄漏
end;
end;//结论是不能正确释放~~
//理所当然不同的数据指针开辟的内存大小就不同,New和Dispose会区分指针的类型~~var
P: Pointer;
begin
New(P);
asm ret end;
Dispose(P);
asm ret end;
New(PString(P));
asm ret end;
Dispose(PString(P));
asm ret end;
asm0047E098 push ebx
0047E099 xor eax,eax
0047E09B call @GetMem
0047E0A0 mov ebx,eax
0047E0A2 ret -----------------------------------
0047E0A3 xor edx,edx
0047E0A5 mov eax,ebx
0047E0A7 call @FreeMem
0047E0AC ret -----------------------------------
0047E0AD mov edx,[$00401080]
0047E0B3 mov eax,$00000004
0047E0B8 call @New
0047E0BD mov ebx,eax
0047E0BF ret -----------------------------------
0047E0C0 mov edx,[$00401080]
0047E0C6 mov eax,ebx
0047E0C8 call @Dispose
0047E0CD ret -----------------------------------
var
P: Pointer;
begin
New(PInteger(P));
asm ret end;
Dispose(PInteger(P));
asm ret end;
New(PInt64);
asm ret end;
Dispose(PInt64(P));
asm ret end;
end;0047E068 push ebx
0047E069 mov eax,$00000004 //分配4个字节 //SizeOf(Integer)=4
0047E06E call @GetMem
0047E073 mov ebx,eax
0047E075 ret -----------------------------------
0047E076 mov edx,$00000004 //释放4个字节
0047E07B mov eax,ebx
0047E07D call @FreeMem
0047E082 ret -----------------------------------
0047E083 mov eax,$00000008 //分配8个字节//SizeOf(Int64)=8
0047E088 call @GetMem
0047E08D ret -----------------------------------
0047E08E mov edx,$00000008 //释放8个字节
0047E093 mov eax,ebx
0047E095 call @FreeMem
0047E09A ret -----------------------------------
Freemem(a,sizeof(a^));
如果确定a是一个结构体指针的化
var
A: Pointer;
begin
Caption := IntToStr(SizeOf(A^)); //0
end;
procedure TForm1.Button1Click(Sender: TObject);
var
P: Pointer;
size1, size2: Integer;
begin
size1 := AllocMemSize;
New(PInteger(P));
Dispose(PInteger(P));
New(PInt64);
Dispose(PInt64(P));
size2 := AllocMemSize; Memo1.Lines.Add(IntToStr(size1) + ' ' + IntToStr(size2));
end;procedure TForm1.Button2Click(Sender: TObject);
var
P: Pointer;
size1, size2: Integer;
begin
size1 := AllocMemSize;
New(PInteger(P));
Dispose(P);
New(PInt64);
Dispose(P);
size2 := AllocMemSize; Memo1.Lines.Add(IntToStr(size1) + ' ' + IntToStr(size2));
end;看源码_FreeMem会调用SysFreeMem
SysFreeMem可以通过传过来的p: Pointer找到一个 TUsed的记录
TUsed = packed record
sizeFlags: Integer;
end;
这个TUsed在GetMem时会保留一个sizeof(TUsed)的大小记录实际分配的内存大小,Dispose(PInt64(P));和
Dispose(P)一个效果,编译器没有用到那个大小信息
而对于PString,记录这种类型则必须
Dispose(PString(P))
因为编译器需要使用这个类型信息来释放内存