我估摸着内存分配+释放是个基础函数,有些人可能没注意此类函数或细究,但我觉得还是弄明白的好。

介绍下面内存函数前,先说一下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及其它函数的区别与相同的更多相关文章

  1. delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同,内存分配函数

    来自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool&utm_medium=referral ---------- ...

  2. Delphi的分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同

    转载自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool 我估摸着内存分配+释放是个基础的函数,有些人可能没注意此类函数或细 ...

  3. 如何在MD(d)和MT(d)工程间正确分配和释放动态内存

    MD(d)和MT(d) MD(d)和MT(d)是windows下VC开发的两个编译选项,表示程序的运行时库编译选项. /MT是"multithread, static version&quo ...

  4. Delphi 内存分配 StrAlloc New(转)

    源:Delphi 内存分配 StrAlloc New 引自:http://anony3721.blog.163.com/blog/static/5119742010824934164/   给字符指针 ...

  5. 分配和释放 BSTR 的内存

    本文档已存档,并且将不进行维护. 分配和释放 BSTR 的内存 Visual Studio .NET 2003                  转自: https://msdn.microsoft. ...

  6. 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现

    http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...

  7. Com组件的内存分配和释放,CredentialProvider SHStrDup 字符串拷贝问题

    一.简单介绍 熟悉CredentialProvider的同学应该知道,他为一个Com组件,于是,在这里的内存分配(字符串拷贝)的一系列操作就要依照con的标准来. 二.Com组件的内存分配和释放 CO ...

  8. FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. 摘:分配和释放BSTR的内存

    当您创建 BSTR的并将它们使用以避免内存泄漏的它们在COM对象之间时,必须注意在将内存的.       当 BSTR 在接口中保持,必须释放其内存,当处理它.       但是,那么,当 BSTR ...

随机推荐

  1. Ajax表单序列化后的数据格式转成Json发送给后台

    <script> $(function(){ //表单转json函数 $.fn.serializeObject = function(){ var o = {}; var a = this ...

  2. Python笔记(1)变量与表达式

    列表list list是用的最多的类型 可以count计数 可嵌套,多钟类型并存 支持 + * a = [1,2,3] a_ref = a a_copy = a[:] 引用,a变化a_ref也变化 指 ...

  3. svn 上传出现Cannot accept non-LF lind endings in 'svn:log'

    可能是你到cimmit日志的字有svn不认的,重新把长传日志删掉,重新敲一遍就好了

  4. 使用自定义tld标签简化jsp的繁琐操作

    最近做一个树形结构的展示,请求目标页面后,后台只返回简单的List,虽然有想过在jsp页面内做一些操作简化,但是太繁琐了,其他的标签又不能满足需求,所以只能自己做一个.使用tld标签可以简化jsp代码 ...

  5. BZOJ4540 [Hnoi2016]序列

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. html页面输入框input的美化

    input输入框是网页必不可少的组件,可是每个浏览器对于输入框的显示样式各有不同 例如:    上图分别就是谷歌浏览器和IE浏览器自带显示的输入框,样式也不足人意,所以大多都会自己写样式 以下是一个简 ...

  7. Protocol Framework - SNMP Tutorial

    30.4 Protocol Framework TCP/IP network management protocols2 divide the management problem into two ...

  8. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  9. Tomcat基本入门知识及发布,虚拟访问及启动碰到的错误,虚拟目录,虚拟路径,各种Tomcat的配置

    Tomcat容器入门介绍 转自javaresearch.com由timgball 整理 Tomcat是一个免费的开源Web服务器,最新版本是5.5.1,支持Servlet2.4,JSP2.0,非常适合 ...

  10. [NHibernate]N+1 Select查询问题分析

    目录 写在前面 文档与系列文章 N+1 Select查询问题分析 总结 写在前面 在前面的文章(延迟加载,立即加载)中都提到了N+1 Select的问题,总觉得理解的很不到位,也请大家原谅,这也是为什 ...