delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同,内存分配函数
来自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool&utm_medium=referral
--------------------------------------------------------------------------------------------------------
我估摸着内存分配+释放是个基础函数,有些人可能没注意此类函数或细究,但我觉得还是弄明白的好。
介绍下面内存函数前,先说一下MM的一些过程,如不关心可忽略:
TMemoryManager = record
GetMem: function(Size: Integer): Pointer;
FreeMem: function(P: Pointer): Integer;
ReallocMem: function(P: Pointer; Size: Integer): Pointer;
end; var
MemoryManager: TMemoryManager = (
GetMem: SysGetMem;
FreeMem: SysFreeMem;
ReallocMem: SysReallocMem);
以上是D7版本的MM函数,其中变量MemoryManager我称为MM函数,请注意。
D2005-D2007以上版本(不确认哪个版本),MM函数多了AllocMem及RegisterLeak/UnRegisterLeak函数,与本文无关,就不多说了。
第三方MM接管的就是这MM的几个函数,达到外挂目地,而Sys打头的SysGetMem, SysFreeMem, SysReallocMem则为本身系统自带的MM处理。
一:New/Dispose
此两函数,估计学delphi/pascal,就知道:为record/object此类数据进行分配和释放内存块
然后分配与释放是调用的是GetMem/FreeMem函数,与GetMem/FreeMem不同之处是:
New()在GetMem后,进行了initialize(x)操作,即对record/object的数据进行初始化的操作.
initialize函数,在system单元,该函数说白了,即对record/object里面中,含有string,interface, dync array,variant,record,array的字段,进行初始化为0(清空).
这一步很重要,因为GetMem返回的内存块可能重复使用过的,使用过的,表示有值。
有值的情况下,再重新赋值,就表示旧地址对应的数据要先清空,清空随机地址的数据?AV就会出现了...
(不要想着,在GetMem后,进行每字段初始化,容易出错的就是这个,在有以上以字段的情况下,如果需要手动初始化,必须用fillchar,原因如上。)
与之相反的Dispose()亦同,反操作,进行清空:finalize(x)后,再进行FreeMem,以保证record/object中,
string,interface/dyncarray字段,不会因为直接调用FreeMem而泄露(leak)
总结是:
a: New==> GetMem(p, sizeof(TDataType)) + Initialize(p^) ==>AllocMem(sizeof(TDataType));
它与AllocMem区别是:initialize(x)不会对每个字节清0,只针对于某些字段清0.
Dispose == Finalize(p^) + FreeMem(p);
没有可代替的函数,也不能少finalize(p^)这步操作,否则会有leak.
b: record/object的指针类型,最好使用此对函数进行分配及释放。当然你也可以去自维护record/object里面的字段生存期。
c: 如果调用system.Initialize/Finalize,出现提示:
[Hint] Unit1.pas(43): Expression needs no Initialize/Finalize
表示record/object里面的字段,没有包含string,interface,dync array,variant,record,array
即表示不需要调用Initialize或Finalize进行操作。
d: 多说一句:每个warn/hint都有其作用,请勿忽略,说不定小BUG就在其中,请关注它们或干掉它们。
二:GetMem/FreeMem
GetMem/FreeMem是MM的分配与释放内存块函数,多说一些是与之相关的:此两函数,会因为分配或释放失败而抛出异常(exception)
而MM对应的标准分配与释放函数是以返回值形态进行处理的,即失败了,只会返回空值(nil)或非0,而不是异常。
也就是说Get/FreeMem是针对于MM的标准函数进行了异常封装。
异常信息:
GetMem fail => Out of memory.
分配失败,一般只会是进程的可用内存分配完毕,通常在内存泄露的情况下才会发生。
FreeMem fail => Invalid pointer operation
两次FreeMem同地址,第二次就有这invalid pointer异常了。:)
三:GetMemory/FreeMemory
Get/FreeMemory与GetMem/FreeMem基本相同,唯一不相同的是,它直接以MM的对应函数的返回值作为返回,而不进行异常处理。
即:GetMem调用MM.GetMem返回为nil,则有异常,而GetMemory则直接返回nil,交给调用者处理
FreeMem调用MM.FreeMem返回非0(错误释放),则异常,而FreeMemory则直接返回0或非0,给调用者处理。
这点非常有用,在写程序时,可以减少异常,或者在Get/Free出现错误时,写句assert(...),让程序中断下来,检查并调试。
四:SysGetMem/SysFreeMem
SysGetMem/SysFreeMem与GetMemory/FreeMemory基本相同,区别在于,它直接调用MM的实现函数,
则不是经过MM的管理器指针再行跳转。
即说:SysGet/SysFreeMem,它使用的是系统自带的MM分配释放函数,当第三方MM加入后,以上三对函数,
都会由第三方MM接管,但SysGet/SysFreeMem它还是调用的本系统自带的MM函数处理,与第三方MM无关。
五:其它
其它还有些Delphi单元的分配释放函数,不过基本是从以上四对函数扩展出来,就不说明了
当然也有从API扩展出来的分配+释放函数,则不在此列,它与D系统的MM扩展无关。
总结:
New+Dispose与GetMem+FreeMem,是基于VCL异常机制保护的分配+释放函数。
GetMemory+FreeMemory与SysGetMem+SysFreeMem是由调用者自行控制返回,来决定是否返回异常或错误处理。
完。
2014.10.19 by qsl
delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同,内存分配函数的更多相关文章
- delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同
我估摸着内存分配+释放是个基础函数,有些人可能没注意此类函数或细究,但我觉得还是弄明白的好. 介绍下面内存函数前,先说一下MM的一些过程,如不关心可忽略: TMemoryManager = recor ...
- Delphi的分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同
转载自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool 我估摸着内存分配+释放是个基础的函数,有些人可能没注意此类函数或细 ...
- new与malloc的区别,以及内存分配浅析
从函数声明上可以看出.malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小.比如: 1 2 3 int *p; p = new int; //返回类型 ...
- 终于懂了:Delphi的函数名不是地址,取地址必须遵守Object Pascal的语法(Delphi和C的类比:指针、字符串、函数指针、内存分配等)good
这点是与C语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ------------------------------------------------- ...
- Com组件的内存分配和释放,CredentialProvider SHStrDup 字符串拷贝问题
一.简单介绍 熟悉CredentialProvider的同学应该知道,他为一个Com组件,于是,在这里的内存分配(字符串拷贝)的一系列操作就要依照con的标准来. 二.Com组件的内存分配和释放 CO ...
- <转载>内存管理内幕-动态分配的选择、折衷和实现 对malloc内存分配有个简单的描述,对内存管理有个大致的说明
这篇文章看后感觉不错,和我在glibc下的hurdmalloc.c文件里关于malloc的实现基本意思相同,同时,这篇文章还介绍了一些内存管理方面的知识,值得推荐. 原文链接地址为:http://ww ...
- 技术回归01-Windows内存分配工具
很久没有写技术方面的东西了,这半年主要是在学习别人的东西,对自己提高比较大,算是一次技术回笼吧,这次学习之旅目的是结束技术方面的专注,开始向应用方面找突破口,也就是完成技术积累或者为技术的积累做坚实的 ...
- RAMCloud:内存云存储的内存分配机制
现在全闪存阵列已经见怪不怪了,EMC的XtremIO,还有VNX-F(Rockies),IBM FlashSystem.全闪存真正为效率而生,重新定义存储速度.凭借极致性能,高可用性,为您极大提高企业 ...
- Linux内核中常见内存分配函数【转】
转自:http://blog.csdn.net/wzhwho/article/details/4996510 1. 原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页 ...
随机推荐
- 剑指offer:跳台阶
目录 题目 解题思路 具体代码 题目 题目链接 剑指offer:跳台阶 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). ...
- ExtJS6.0扩展日期选择控件为也可以选择时间
PS:ExtJS自带的日期选择控件只能够选择日期,但是现在的需求需要精确到秒,所以在网上搜索了一些例子(大部分是4.0的)作为参考,然后改出了6.0可用的一个日期时间选择控件. 1.找到extjs6. ...
- 【EasyNetQ】- 控制队列名称
在为队列生成名称时,EasyNetQ的默认行为是使用消息类型名称并将其附加到订阅ID.例如PartyInvitation,命名空间中的消息类型EasyNetQ.Tests.Integration将使用 ...
- 不错的PDF开发库
C++库: 1,PDF类库 PoDoFo http://podofo.sourceforge.net/ PoDoFo 是一个用来操作 PDF 文件格式的 C++ 类库.它还包含一些小工具用来解析 ...
- WebKit资源加载和网络栈
webkit笔记,主要来自 朱永盛 <WebKit技术内幕> 学习笔记,转载就注明原著,该书是国内仅有的Webkit内核的书籍,学习的好导师,推荐有兴趣的朋友可以购买 WebKit资源加载 ...
- 【bzoj1391】[Ceoi2008]order 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend/p/6796937.html 题目描述 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序 ...
- json数据中的某一个字段进行快速排序quicksort
快速排序(Quicksort)是对冒泡排序的一种改进,是一种分而治之算法归并排序的风格. 核心的思想就是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小 ...
- [BZOJ4920][Lydsy六月月赛]薄饼切割
[BZOJ4920][Lydsy六月月赛]薄饼切割 试题描述 有一天,tangjz 送给了 quailty 一张薄饼,tangjz 将它放在了水平桌面上,从上面看下去,薄饼形成了一个 \(H \tim ...
- Contest Hunter 模拟赛09 A [线段树维护斜率]
题面 传送门 思路 首先看看我们到底要干什么:有$1e6$次询问,遍历$i$,每次要求一个形如$b_i \ast a_j - a_i \ast b_j$的东西的最大值 考虑如果一个$j$的决策在当前的 ...
- 洛谷 P1415 拆分数列 解题报告
拆分数列 题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数. 如果有多组解,则输出使得最后一个 ...