请教两个关于内存的高难度问题 ( 积分: 200 )

  • 主题发起人 主题发起人 FreeAndNil
  • 开始时间 开始时间
F

FreeAndNil

Unregistered / Unconfirmed
GUEST, unregistred user!
1<br>pchar类型,比如getmem(p,40)后,如果在第20个字节处手工写入/0,那p的长度是多少?调用freemem释放,忽略size参数,会释放多少字节?40?还是20?<br><br>2<br>string类型,如果一个string:s,赋值了一个50字节长的字符串,length(s)=50,根据string的结构,s地址前4个字节是长度,如果手工修改,把50改为20,等这个字符串作用域结束了,自动释放,是释放50个字节还是20个字节?或者,我修改string的内容,在第20个字节写入/0,释放时会怎样?<br><br>以上两种做法,是否会造成内存泄漏?<br><br>再附加一个问题:<br>getmem(p,20)后,freemem(p,50),freemem(p,10),都不会出错,而且内存也都释放干净了,这个size参数有什么用?
 
不懂,只好给你顶下吧。<br>我个人的答案是<br>1.我觉得如果调用length(p)应该是19,释放会释放20。<br>2.我怎么好像记得string的第一个字节是长度啊,不是4个呢。自动释放当然是释放50个吧。修改20,释放还是会全部释放吧。<br>1会造成泄漏,2不会。<br>参数应该是让你自己控制释放多少吧,呵呵。如果是一个记录体可以先释放一部分。
 
1&nbsp;比如getmem(p,40)后,OS自动在内存快中定义了长度就就是40了,<br>&nbsp;&nbsp;所以freemem(p,50),freemem(p,10),都不会出错,OS自己认得是40<br>&nbsp;&nbsp;OS&nbsp;是操作系统内存管理机制,《操作系统〉〉书上有!<br><br>2.&nbsp;string类型,道理也是一扬,你可以调试SetLengTh,&nbsp;你会发现Delphi先释<br>放原来的分配内存,再malloc分配心的内存空间!<br><br>&nbsp;&nbsp;呵呵!董了吗!
 
顶一下……
 
今天不想写程序了,也来灌水。<br>1<br>pchar类型,比如getmem(p,40)后,如果在第20个字节处手工写入/0,那p的长度是多少?调用freemem释放,忽略size参数,会释放多少字节?40?还是20?<br>A:长度从0-19都有可能;释放会是正确的40,DELPHI将块大小存于块本身。<br>&nbsp;&nbsp;&nbsp;注:DELPHI是自己实现堆管理的,不是使用OS的。<br>2<br>string类型,如果一个string:s,赋值了一个50字节长的字符串,length(s)=50,根据string的结构,s地址前4个字节是长度,如果手工修改,把50改为20,等这个字符串作用域结束了,自动释放,是释放50个字节还是20个字节?或者,我修改string的内容,在第20个字节写入/0,释放时会怎样?<br>A、修改长度,不会引起内存泄露,因为还有额外的块大小;你在串内容中在写任何东西,都中内存管理无关了。<br><br>再附加一个问题:<br>getmem(p,20)后,freemem(p,50),freemem(p,10),都不会出错,而且内存也都释放干净了,这个size参数有什么用?&nbsp;&nbsp;<br>A、size参数,是为了向后兼容。以前版本的DELPHI内存管理器,可能没有将块大小存到块中。
 
我个人认为与具体的实现有关。也就是说不同的操作系统、编译器可能会有不同的结果。最好的办法是自己编程试一试!
 
块是什么概念?存在什么地方?有什么作用?能讲一下吗?
 
释放内存时只是把内存块的标记标为“未用”和内存里面是什么内容无关。<br>一般进程内的可用内存分堆和栈。区别如下:<br>栈的大小是固定的,堆的大小是活动的。<br>栈很小,堆大<br>栈操作速度快,堆操作速度慢。<br>“块”状内存是在堆中分配的。并由delphi的内存管理器自行维护。<br>块是内存的一种管理方式,你可以理解为一“块”就是一个小格子,小格子内可以放东西。<br>delphi内存管理器首先会向系统申请一个大的“块”<br>然后你的代码内消耗的内存,就从这大块内切分小块来用,如果有多个释放的小块,则会试图合并。<br>如果这个大块用完了,会再向系统申请大的块。<br><br>比如,你在过程内申明一个局部变量&nbsp;var&nbsp;s:&nbsp;string;<br>那么,这个s的指针将在栈上分配<br>而s内的字符串是分配在堆中的,因此,理论上s允许有2G的容量。
 
/0&nbsp;只是字符串的结束标志,和内存没什么关系.<br>getmem(p,40),在第20个字节处手工写入/0<br>string&nbsp;s;<br>s&nbsp;:=&nbsp;p;<br>s的长度只有20;<br>对于string&nbsp;修改存储的字符长度的值,不会影响内存空间。你把string类型理解成一个结构体p-&gt;string&nbsp;这样你修改的只是结构体中的值
 
块是什么概念?存在什么地方?有什么作用?能讲一下吗?
 
我对块的理解就是多少位,一般情况下指的是8位一个字节。
 
支持&nbsp;东兰梦舞<br>&nbsp;&nbsp;&nbsp;&nbsp;这些是和Delphi的内存管理有关系的,&nbsp;可以去看下&nbsp;周爱民的&lt;&lt;Delphi&nbsp;源代码分析&gt;&gt;里面有说的.&nbsp;其实你getmem&nbsp;返回的内存前面还有东西[:D]
 
1&nbsp;不会&nbsp;<br>2&nbsp;不会&nbsp;string的长度是放在数据体的前面的&nbsp;长度位大概保存在Pinteger(str)-4,具体位置请查看system.pas<br>3&nbsp;freemem(p,size)&nbsp;的size参数位,可以不输入&nbsp;,freemem(p)和&nbsp;freemem(p,size)是一样的,猜测是内存管理器记住了给某个地址分配了多少长度,释放的时候自行处理长度
 
1.40,释放的时候并不依赖/0来获取长度。<br>2.这个问题要首先说一下,我想你可能是没有区分string分配的内存大小与字符个数之间的关系,正常的情况是字符的个数+9(4个字节的长度+4个字节的引用计数+一个字节的/0),但如果你使用setlength等函数分配那就不是这个关系了。另外释放的时候同上也不依赖于长度,这个长度偏移只是为了提高效率及length使用。<br>3.关于这个freemem你可以参考帮助,应该说得很明白。<br>注:如果你对delphi的内存管理有兴趣可以看楼上推荐的那本书不过可能要一点基础,也可以直接看getmem.inc这个文件,它是delphi默认的内存管理器的源代码。
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部