procedure New(var P: Pointer);  {为一个指针变量分配内存,会自动计算指针所指数据结构需要空的空间大小}

procedure GetMem(var P: Pointer; Size: Integer); {分配一个指定大小的内存块(连续),并用P指向它}

procedure ReallocMem(var P: Pointer; Size: Integer);{重新分配指定大小内存块,参数P必须是nil或者指向一个由GetMem, AllocMem, 或 ReallocMem分配的内存变量,其分配的内存是连续的,会把前面已有的数据移到新分配的内存中去}

通常采用New分配内存比较好。

一、New和GetMem都可以为指针类型动态分配内存,并且Delphi不会对由此分配的内存进行管理,即必须有相应的代码对其进行释放,否则内存将“丢失”,直到应用程序结束。  
  二、New分配的内存必须由Dispose来释放;GetMem分配的内存必须由FreeMem来释放;  
  三、New根据指针类型来自动计算需要分配的内存尺寸;GetMem必须指定尺寸;  
    
  因此,对于类型指针,一般用New和Dispose来进行管理;对于内存尺寸随机的指针(典型地如PChar),一般用GetMem和FreeMem来进行管理。从另一方面来说,在很多时候用哪一对例程都可以进行动态内存管理。

New 和 GetMem 的不同之处

如果操作一个 record 指针中的字符串变量,会不会丢失 string 的内存空间,造成内存泄漏? 
结果是:使用 New() 分配的内存,会自动初始化 record 的内容,并且在 Dispose 时自动 
清除所有已分配的内存,包括 string 或其他动态数组的内存。GetMem/FreeMem 没有这个 
性质。事实上,New() 中调用了 GetMem,并且执行了一些初始化的操作。

代码如下:

type 
PMyRecord = ^TMyRecord; 
TMyRecord = record 
I: Integer; 
S: string; 
V: Variant; 
end;

{;$DEFINE NEW}

procedure TForm1.Button1Click(Sender: TObject); 
var 
R: PMyRecord; 
I: Integer; 
begin 
for I := 1 to 1024 do 
begin 
{$IFDEF NEW} 
New(R); // 正确将 R.S 初始化 
SetLength(R.S, $FFFF); 
Dispose(R); // 正确释放 R.S 内存空间 
{$ELSE} 
GetMem(R, SizeOf(TMyRecord)); 
R.S := ''; // 出错 
SetLength(R.S, $FFFF); 
FreeMem(R); 
{$ENDIF} 
end; 
end;

===================================================

GetMem 只负责分配空间,不会负责清空刚分配的空间,如果需要分配来就 
清空的空间可以用 AllocMem,AllocMem = GetMem + FillChar

===================================================

哦,我上面犯错误了,以为 S = 0 时也会出错,所以没有 FillChar,其实不会。

这样就可以正确测出结果了: 
(将 $DEFINE NEW 前面的 ; 去掉,可以从任务管理器中查看二种方法的内存占用)

type 
PMyRecord = ^TMyRecord; 
TMyRecord = record 
I: Integer; 
S: string; 
V: Variant; 
end;

{;$DEFINE NEW}

procedure TForm1.Button1Click(Sender: TObject); 
var 
R: PMyRecord; 
I: Integer; 
begin 
for I := 1 to 1024 do 
begin 
{$IFDEF NEW} 
New(R); // 正确将 R.S 初始化 
SetLength(R.S, $FFFF); 
Dispose(R); // 正确释放 R.S 内存空间 
{$ELSE} 
GetMem(R, SizeOf(TMyRecord)); 
FillChar(R^, SizeOf(TMyRecord), #0); 
SetLength(R.S, $FFFF); 
FreeMem(R); // 不会释放 R.S 内存空间 !! 
{$ENDIF} 
end; 
end;

===================================================

是的,FreeMem 不会释放其中的生存期自动管理的内容,因为在 FreeMem 
看来,那些都是一致的二进制数据,没有任何意义可言。不过可以通过一个 
Finalize 调用(或者 FinalizeRecord)解决该问题 我估计 Dispose 就直接 
或间接调用了 Finalize

===================================================

呵呵,不用估计,帮助中明确地说明了。

In Delphi code, FreeMem destroys the variable referenced by P and returns its memory to the heap. If P does not point to memory in the heap, a runtime error occurs. If P points to a structure that includes long strings, variants, dynamic arrays, or interfaces, call Finalize before calling Freemem. 
...... 
Note: It is preferable to use the New and Dispose procedures rather than GetMem and FreeMem. When using New and Dispose, there is no need to explicitly call Finalize. 
这段英文我翻译一下。 
“在DELPHI代码中,FreeMem根据变量所引用的指针释放内存,并将内存归还给堆。如果指针不是指向堆中的内存地址,将发生一个运行时错误。如果指针所指向的是一个数据结构,且其中包含有长字符串、Variants、动态数组、或接口,则在使用用FreeMem之前须调用Finalize ” 
"注意:使用New 和 Dispose 过程要强于使用GetMem与FreeMem。但我们使用New和Dispose的时候,不需要显示的调用Finalize " 
翻译完了。肯定有不准确的地方。 
不过我有一个问题,内存分配既然new和Dispose要比GetMem与FreeMem容易使用,那么还有没有必要使用GetMem、FreeMem,在什么情况下使用它们? 
===================================================
内存分配既然new和Dispose要比GetMem与FreeMem容易使用 
“容易使用”通常只能是一个相对的概念,在这里,我们讨论指向结构体的指针,在这种情况下,New/Dispose 通常是易用的。但是它们是有局限的,就是那个指针指向的空间的大小必须能够在编译期间确定,它们才知道需要分配多大的空间。对于指向结构体的指针,这个值就是结构体的大小,这当然是确定的,所以能够使用它们,并且能够带来便利。 
可是还有一些情况,例如你只有一个 Pointer 类型,这是无类型指针,你把它传给 New,编译器就不知道它指向的是什么内容,也就不知道它指向的空间有多大,也就不知道需要分配多少空间,就根本不能用,更不用说易用了。 
还有没有必要使用GetMem、FreeMem,在什么情况下使用它们? 
当然有了,如前面提到的,相对来说,New/Dispose 操作更为高层一些,我们通常用它们来操作指向结构体的指针,即是说指针指向的内容是编译期间就已知的数据结构。而当我们需要更加低级的去操作一些内存空间的时候,比如你要自己处理字符串的时候,你的指针指向的就是只有你自己才知道或者说是你自己去进行理解的内存空间,没有编译期间的明确的数据结构与之对应。这个时候,就要用到 GetMem/FreeMem 了。 
所以说,New/Dispose 的局限性实际上是很大的,或者说适用范围是很小的,而 GetMem/FreeMem 给了我们充分的自由,试用范围更广。当然,具体选用哪个,还要看实际情况而定。

http://blog.csdn.net/luo809976897/article/details/12851763

New,Getmem,ReallocMem联系与区别(转)的更多相关文章

  1. Delphi New,Getmem,ReallocMem联系与区别

    来自:http://www.cnblogs.com/jsrgren/archive/2011/10/31/2270353.html ---------------------------------- ...

  2. AQTime教程(1)

    AQTime教程 1 简介 AQTime和MemProof都是AutomatedQA旗下的产品,AQTime比MemProof提供了更丰富强大的功能.该产品含有完整的性能和调试工具集,能够收集程序运行 ...

  3. AQTime教程

    1 简介 AQTime和MemProof都是AutomatedQA旗下的产品,AQTime比MemProof提供了更丰富强大的功能.该产品含有完整的性能和调试工具集,能够收集程序运行时关键的性能信息和 ...

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

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

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

    我估摸着内存分配+释放是个基础函数,有些人可能没注意此类函数或细究,但我觉得还是弄明白的好. 介绍下面内存函数前,先说一下MM的一些过程,如不关心可忽略: TMemoryManager = recor ...

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

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

  7. delphi dispose释放内存的方法 New 和 GetMem 的区别

    来自:http://blog.sina.com.cn/s/blog_4bc47d2301018trf.html -------------------------------------------- ...

  8. Delphi中那些容易混淆的基础(@、^、Addr、Pointer,Move、CopyMemory,GetMem和FreeMem、GetMemory和FreeMemory、New和Dispose、StrAlloc和StrDispose、AllocMem)

    @.^.Addr.Pointer Delphi(Pascal)中有几个特殊的符号,如@.^等,弄清楚这些符号的运行,首先要明白Delphi指针的一些基础知识:指针,是一个无符号整数(unsigned ...

  9. Delphi中堆栈区别

     http://blog.csdn.net/zang141588761/article/details/52838728 Delphi中堆栈区别 2016-10-17 14:49 277人阅读 评论( ...

随机推荐

  1. PAT 1051-1060 题解

    浏览全部代码:请戳 本文谨代表个人思路,欢迎讨论;) 1051. Pop Sequence (25) 题意 给定 stack 的容量,给定数据的入栈顺序:从 1 开始的正整数序列,在允许随机的出栈操作 ...

  2. 新世界PT850/PT853检查用友机对接T1交易宝

    新世界PT850/PT853检查用友机对接T1交易宝 这是一个老话题.简单.条形码号码模式是没有必要说,我要说的是,,启用条码扫描.显示有关信息. 并能够产生:条码 , 数量,价格格 这样做的目的.将 ...

  3. SQL中关键字的执行顺序

    作为一个SQL新手,看到每种不熟悉的关键字时已经够迷茫了,可往往见到的语句关键字顺序还是各种各样,太难理解了.网上搜索了两篇文章,总结一下: 关于Sql关键字SELECT FROM GROUP ORD ...

  4. Android - Earthquake工程(地震监测) 的 对

    Earthquake工程(地震监测) 的 对 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24465487 Earthquake ...

  5. 如何停止处于stopping状态的windows服务(使用taskkill)

    工作中有时需要启动和停止windows service,有时候会出现服务处于stopping或者starting的状态,但是,在services界面中,start service/stop servi ...

  6. WPF 定时器DispatcherTimer+GetCursorPos 的使用,动态查看屏幕上任一点坐标

    原文:WPF 定时器DispatcherTimer+GetCursorPos 的使用,动态查看屏幕上任一点坐标 );                           dTimer.Start(); ...

  7. Android发展_备份短信

     短信备份的原理 短信备份的原理.是用内容提供者读取短信,然后保存. public class SmsBackupUtils { // 回调接口 public interface SmsBacku ...

  8. 日志文件 清理or压缩

    1.操作前请断开所有数据库连接. 2.分离数据库 分离数据库:企业管理器->服务器->数据库->cwbase1->右键->分离数据库 分离后,cwbase1数据库被删除, ...

  9. 同时使用SpringJUnit4ClassRunner和Parameterized进行参数化

    标题实际上是个不可能完成的任务,因为我们只能用一个Runwith注解,而且只能写一个类,但是我们可以曲线救国,插入下方的5到14行就可以注入了 @ContextConfiguration(classe ...

  10. 为什么腾讯总能做出好产品?(在互联网行业,往往仅凭一个关键产品就足以改变整个公司的格局)MSN失败在不以用户体验为中心

    投递人 itwriter 发布于 2017-07-10 11:16 评论(36) 有3401人阅读 原文链接 [收藏] « » 本文来自微信公众号“郑志昊 Peter”,作者李翔.郑志昊:博客园经授权 ...