如果操作一个 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.

===================================================
guttier wrote: 
呵呵,不用估计,帮助中明确地说明了。

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/henreash/article/details/4235242

New 和 GetMem 的不同之处的更多相关文章

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

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

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

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

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

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

  4. New,Getmem,ReallocMem联系与区别(转)

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

  5. CSS预处器的对比——Sass、Less和Stylus

    预处器的对比--Sass.LESS和Stylus 转载: 英文原文:http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less ...

  6. 数据库(SQL Server)管理数据库表~新奇之处

    说到“数据库”,我总有一种莫名的感觉,在刚刚接触到的数据库中就让我似懂非懂渡过着,于是思考着.于是在冷静的时空中让我回想到了很多的知识,不知你们是怎样过来的,真心希望我的这篇数据库总结能够让我们都有一 ...

  7. Autocad 2012 win7(64位)启动时一直卡在acmgd.dll处的解决方案

    安装Autocad 2012后,激活成功后,无法正常启动,一直卡在加载acmgd.dll 通过Procmon监控后发现加载C:\Windows\fonts\AdobeFnt11.lst处出错, 通过命 ...

  8. this的安身之处

    在JavaScript的大千世界中,this对象就像一个行踪不定.居无定所的浪子一般,它的生活仿佛可以随处而安,而内心却又似有着笃定的坚守,它就是这么有趣! 初学JavaScript时的我们,多多少少 ...

  9. OO方式下,ALV TREE和ALV GRID的不同之处

    作为大部分报表程序的基础,ALV GRID差不多是每个ABAP开发者必须了解和掌握的内容,因此网上也不乏相关资料,而ALV TREE的应用相对较少,中文资料也就比较少见了.实际上,ALV TREE和A ...

随机推荐

  1. java 发送邮件 email相关操作代码测试,生成复杂格式邮件,发送邮件相关操作

    项目源码下载:http://download.csdn.net/detail/liangrui1988/6720047 效果图: 相关代码: test1 package com.mail; impor ...

  2. 获取客户端IPAsp.Net

    #region 获取客户端IP地址 /// <summary> /// 获取客户端IP地址 /// </summary> /// <returns></ret ...

  3. haproxy 配置日志

    jrhppt01:/root# vim /etc/haproxy/haproxy.cfg # this config needs haproxy-1.1.28 or haproxy-1.2.1 glo ...

  4. poj2533--Longest Ordered Subsequence(dp:最长上升子序列)

    Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 33943   Acc ...

  5. C++ 左值 右值

    最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 )   参考:<Boost程序库探秘——深度解析C ...

  6. 梳理一下uboot是如何从nandflash挂载文件系统的

    只是找到了比较一点点的线索, 如下: 首先要有的概念是,内核在挂载文件系统之前,自己会做一个虚拟fs. 1. Uboot:从flash启动set bootcmd nand read 0x3000000 ...

  7. 柔性数组-读《深度探索C++对象模型》有感

    最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下 ...

  8. 打算自己做app,你们做过吗?

    最近手头上资金不足,想自己搞一下app赚点广告费,解决一下自己的零花钱问题,各位有没有做自己的app呢?打算用有米广告,各位觉得怎么样? 你们的收益是如何呢?能在这里晒晒吗?

  9. EasyUI - DataGrid 组建 - [ 组件加载和分页 ]

    效果: 原理:通过POST传递到数据后台字段. 此时上传的参数,page:当前页数,rows:每页显示的页数. 有此两项参数,计算取出数据条数. 通过后台接受参数,进行处理并返回抽取的数据. html ...

  10. 重操JS旧业第五弹:函数

    函数在任何编程语言中起着非常重要的位置,因为他是功能的最小单元,在js中函数是一种类型 Function 1 申明与定义 显示声明:function cc(){};函数名其实是函数的一个指针,函数名某 ...