Dai*_*tsu 8 memory delphi parameters memory-management delphi-6
我有很多内存分配和相同数量的FreeMem调用.我没有的是在调用freemem之前检查指针是否为nil,以及释放后将指针设置为nil后的一行.
我试图创建一个函数来做到这一点
procedure FreeMemAndNil(p: Pointer; size: Integer = -1);
begin
if p <> nil then
begin
if size > -1 then
FreeMem(p, size)
else
FreeMem(p);
p := nil;
end;
end;
Run Code Online (Sandbox Code Playgroud)
但是有一个问题.它不能将原始指针设置为nil,因为参数不可变(var p:Pointer).我不能使用var,因为如果我做编译器抱怨类型必须是完全相同的类型(指针).我传递的指针可以指向任何类型的指针(PChar,常规指针等).
我该怎么做才能解决这个问题?有更好的解决方案吗?
Rob*_*edy 13
为了能够将任意指针值传递给该函数,您需要遵循与FreeAndNil相同的模型并传入无类型参数.否则,编译器会正确地抱怨实际和形式参数类型不相同.当您在其上调用FreeMem时,将无类型参数键入类型转换为Pointer.
你在这个功能中做了几件毫无意义的事情.
首先,释放nil指针始终是安全的,因此在调用FreeMem之前没有理由检查它.它释放了一个你需要担心的非零指针,但没有任何功能可以保护你.
接下来,FreeMem的size参数已被忽略多年.过去,如果你提供了这个参数,它需要匹配传递给GetMem的大小,但是现在,FreeMem完全忽略了那个参数 - 编译器甚至没有将该参数传递给函数.
考虑到以上所有因素,您的功能归结为:
procedure FreeMemAndNil(var P);
var
Tmp: Pointer;
begin
Tmp := Pointer(P);
Pointer(P) := nil;
FreeMem(Tmp);
end;
Run Code Online (Sandbox Code Playgroud)
注意不要在不是用GetMem分配的指针的任何东西上意外调用该函数.如果您使用的是类型化参数,编译器将不会像您一样捕获它.如果你试图释放没有用GetMem分配的东西,你可能会得到一个EInvalidPointer异常,但你传入的变量在之后仍然是零.这与FreeAndNil的工作方式相同.
在SysUtils中有一个名为FreeAndNil的程序,它为对象执行此操作.它是通过使用它转换为TObject 的无类型var参数来实现的,并且由你决定不传递它不是TObject的东西.如果需要,你可以在这里做类似的事情.小心点 如果你这样做,没有类型安全.
像梅森惠勒说,你应该使用相同的伎俩FreeAndNil在sysutils的单位确实对对象的引用.
所以我修改了你的代码,对它进行了单元测试,这很好用:
procedure FreeMemAndNil(var ptr; size: Integer = -1);
var
p: Pointer;
begin
p := Pointer(ptr);
if p <> nil then
begin
if size > -1 then
FreeMem(p, size)
else
FreeMem(p);
Pointer(ptr) := nil;
end;
end;
Run Code Online (Sandbox Code Playgroud)
--jeroen
PS:Rob Kennedy为无类型的var参数写了一个很好的答案,这些参数有一个链接到他在互联网上的无类型参数页面.
PS2:供参考:Kysix 版本的SysUtils.pas是在线的,FreeAndNil与Delphi中的版本相同.
| 归档时间: |
|
| 查看次数: |
5436 次 |
| 最近记录: |