我做了一个简单的例子,释放一个结构指针时并不需要指针类型
但是前一段时间做一个项目里,没指定指针类型释放就造成了内存泄漏
后来修改为指定指针类型的释放就没有问题了所以现在有点迷惑了,到底需要不需要指定指针类型?
或者是有的情况下需要有的情况下不需要?
请各位高手谈谈经验.
但是前一段时间做一个项目里,没指定指针类型释放就造成了内存泄漏
后来修改为指定指针类型的释放就没有问题了所以现在有点迷惑了,到底需要不需要指定指针类型?
或者是有的情况下需要有的情况下不需要?
请各位高手谈谈经验.
解决方案 »
- chart中series画线的问题 才发现的。。。。刚才的点错小论坛了。。。。
- 录音的微弱问题
- 问一个日期格式定义问题,大家帮忙看下,谢谢·
- delphi中如何添加realaudio控件,请高手指教?
- 关于idhttp.Request.UserAgent的默认值
- delphi 有没有这方样的功能/工具?
- delphi真强,熊猫烧香居然是delphi写的!
- 如果用Delphi,在win2000或winxp或win2003的系统栏右下角显示黄色的提示框
- TBatchMove控件的batAppend模式总是出错,而batcopy则正常
- IntraWeb,WebSnap,Web broker,可视化Web开发,太酷了!!!
- 怎样开发应付系统呀
- delphi中的大数异或
procedure _Dispose(p: Pointer; typeInfo: Pointer);
不提供原型的话,Finalize(System._Finalize)将无法得到正确的类型信息,对于string、动态数组等类型将没法清理没leak的record里肯定是没有string和动态数组类型的,有leak的record里至少有两者之一
Unit1.pas.192: Dispose(TL[I]);
0048D465 8BD3 mov edx,ebx
0048D467 8B4640 mov eax,[esi+$40]
0048D46A E88901F9FF call TList.Get
0048D46F 33D2 xor edx,edx
0048D471 E80657F7FF call @FreeMem// 下面是FreeMem的汇编代码
00402B7C 53 push ebx
00402B7D 85C0 test eax,eax
00402B7F 7415 jz +$15
00402B81 FF1544E04800 call dword ptr [MemoryManager + $4]
00402B87 8BD8 mov ebx,eax
00402B89 85DB test ebx,ebx
00402B8B 740B jz +$0b
00402B8D B002 mov al,$02
00402B8F E838010000 call Error
00402B94 EB02 jmp +$02
00402B96 33DB xor ebx,ebx
00402B98 8BC3 mov eax,ebx
00402B9A 5B pop ebx
00402B9B C3 ret 贴上来看是不是有用.
Fastmm4,
SysUtils;type
PPerson = ^TPerson;
TPerson = record
Name: string;
Age: Integer;
end;var
s: string;
p: Pointer;begin
try
s := 'Bob';
GetMem(p, SizeOf(TPerson));
Initialize(p);
PPerson(p).Name := s;
Dispose(p);
except
on e: Exception do
Writeln(e.Classname, ': ', e.Message);
end;
end.
GetMem要和FreeMem配对
New和Dispose配对
FreeMem 让内存管理器释放之前申请的存储空间,且没有清理(Finalize)既然GetMem和FreeMem已经能申请和释放内存了,那为什么还需要New和Dispose呢?
答案很简单,由于Delphi的某些基本类型(如字符串、动态数组、Record、Array、Interface等)是由编译器自动管理生命周期或引用计数,所以必须在内存申请成功后初始化内存,并且保证在释放内存前完成清理动作(比如减少字符串的引用计数)。可以说,New/Dispose只是封装了GetMem/FreeMem,并做了初始化/清理动作。上面的例子中,执行PPerson(p).Name := s; 之后,s字符串的引用计数已经变成了2,如果这个时候直接调用FreeMem并没有减少s的引用计数,从而导致内存泄露。说到这里,顺便补充一下,正如二楼Seamour所说,如果你传给Dispose的是无类型指针(Pointer),编译器就不知道如何清理(无类型信息),也不会去调用Finalize,效果就和直接调用FreeMem一样。
s: string;
至于释放多少字节,是由指针本身分配时的大小决定的,dispose不理会这一点,它直接调用freemem,让freemem去查找指针原来分配的大小,大龙驹列出的原码已经说明了这一点 这个是我从别的贴子里找到的一段话(http://topic.csdn.net/t/20050605/15/4060604.html),我觉得他说的好像有点道理,看Dispose的汇编代码,它好像也只调用了FreeMem,没有给FreeMem说明是什么类型的指针.
{$IFDEF PUREPASCAL}
begin
_Finalize(p, typeinfo);
FreeMem(p);
end;
{$ELSE}
asm
{ -> EAX Pointer to object to be disposed }
{ EDX Pointer to type info } PUSH EAX
CALL _Finalize
POP EAX
CALL _FreeMem
end;
{$ENDIF}不需要调用_Finalize的只调用了FreeMem,这只能说明delphi的编译器还不至于蠢到涉及底层还要多调用一次没用的函数的程度,虽然跟ms的比已经够笨的了
呵呵,他说的没错,只不过你理解错了。内存管理器只负责分配和释放内存(存储空间),(我猜)它会记录所分配的内存的位置、大小和是否释放的标志。如果这块内存上面有其他的“引用”类型变量(如字符串变量、接口等),就需要使用Dispose(Dispose会调用Finalize)来完成清理动作。