请问一个Tstringlist内存分配问题 “111”大概占8个字节,应该还有一个指针4字节,共12字节,每秒50个,每秒增加600个字节,一分钟36k,十分钟360k,可能还有其他开销,到500k也很正常。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如果a没有释放一直调用add方法内存会一直增加,你这样的结果是111111111... 我的困惑是:我用idhttp获取网页中的链接,然后将这些链接以字符串的形式存放到一个tstringlist中,每个tstringlist成员字符串长度不会超过100个字符。我注意到:当tstringlist ADD到500个的时候,程序占用内存增加了4-5M,500个100字符的字符串有占这么大空间吗?程序其他部分都停止运行了,不存在其他消耗内存的东东了,这是为什么? Delphi的字符串包括一个标志字符串长度的无符号整数,有8位和32位两种,一般是32位,4字节,后面还有一个字节的0以兼容c。 说一个丢人的事,一次程序里面额List不断Add一个对象,但是处理的功能(取出指针,处理、释放、删除)没有跑起来,一天下来13个小时,我查看该进程的虚拟内存达到1.4G. 我的困惑是:我用idhttp获取网页中的链接,然后将这些链接以字符串的形式存放到一个tstringlist中,每个tstringlist成员字符串长度不会超过100个字符。我注意到:当tstringlist ADD到500个的时候,程序占用内存增加了4-5M,500个100字符的字符串有占这么大空间吗?程序其他部分都停止运行了,不存在其他消耗内存的东东了,这是为什么? Delphi的 TStringList部分的源码:TStringList中包括一个称为FList的指针,其类型为Point Of TStringItem,而TStringItem这个类型的定义为 TStringItem = record FString: string; FObject: TObject; end;该结构体最小需要占8个额外的字节。此外,procedure TStringList.Grow;var Delta: Integer;begin if FCapacity > 64 then Delta := FCapacity div 4 else if FCapacity > 8 then Delta := 16 else Delta := 4; SetCapacity(FCapacity + Delta);end;表明TStringList的最大可能会有1/4的空余容量多出来,也就是说,LZ分配的500个String,其实开在内存中的结构可能是650个。但是这一点差异应当不足以成为内存占用增加4~5M的理由。所以会不会是idhttp来抓链接的过程中发生了内存泄露状况,譬如说PChar没有释放掉之类的?或者是内存碎片太多? 以下是抓取的过程,看看有无问题?function findbt._Get(var url,scookie : String;var idh:tidhttp) : String;var stream,outstream : TMemoryStream; decomp : TIdCompressorZLibex; resp : TStringlist;begin try stream := TMemoryStream.Create; resp := TStringList.Create; idh.Request.CustomHeaders.Text :=scookie; idh.Get(url,stream); stream.Position := 0; if AnsiCompareText('gzip',idh.Response.ContentEncoding) = 0 then begin try decomp := TIdCompressorZLibex.Create(nil); outstream := TMemoryStream.Create; decomp.DecompressGZipStream(stream,outstream); outstream.Position := 0; resp.LoadFromStream(outstream); finally freeandnil(decomp); freeandnil(outstream); end; end else resp.LoadFromStream(stream); Result := resp.Text; idh.Disconnect ; freeandnil(stream); freeandnil(resp); except idh.Disconnect ; freeandnil(stream); errorflag:=1; freeandnil(resp); end;end; delphi的内存释放不是把内存返回给系统,而是标记为可用,下次申请时继续使用,所以你会感觉申请的内存不断的增大 一方面 Delphi的内存管理器不会立刻回收,而是有自己的调度规则.另一方面,新的内存块未必就是你给他那么大,他有一个对齐方式.比如4KB对齐.你不停的分配,实际上会产生比较多的碎块.还有内存管理器管理的时候每个内存块都会有一个描述信息.Delphi的默认是用链表管理的.大量的小块数据就会产生比较多的链表节点,每个节点再有一点描述信息.当然会大.VC一般是放在负偏移有一个描述块,结果是一样的. 程序中需要储存量比较大的字符串,存放在tstringlist和数组里哪个比较好一点?如果需要频繁使用tstringlist,是对其频繁free-creat好呢?还是不断clear使用好呢?谢谢 如何停止杀毒软件服务 没有注册类别! Application.messagebox造成死机 datetimepicker 的用法 想在多媒体教学软件(课件)开发领域发展,希望各位知道有这方面公司招人的请告知,不胜感激!!!有分。 散分..不散分对不起人民群众!!!!! 请教EDIT控件输入格式的确定? 请问如何把内存映射文件的内容修改并保存到原文件中 关于考程序员的事情想请教各位 请问哪里有delphi的并口通信的控件 ▲▲▲ 请问这个DBGrid是用什么做的,请指点下 ▲▲▲ DBChart中,Series.VertAxis与CustomAxes[x]关联,y轴数据不能放大缩小
111
111
111
...
我的困惑是:
我用idhttp获取网页中的链接,然后将这些链接以字符串的形式存放到一个tstringlist中,每个tstringlist成员字符串长度不会超过100个字符。我注意到:当tstringlist ADD到500个的时候,程序占用内存增加了4-5M,500个100字符的字符串有占这么大空间吗?程序其他部分都停止运行了,不存在其他消耗内存的东东了,这是为什么?
我用idhttp获取网页中的链接,然后将这些链接以字符串的形式存放到一个tstringlist中,每个tstringlist成员字符串长度不会超过100个字符。我注意到:当tstringlist ADD到500个的时候,程序占用内存增加了4-5M,500个100字符的字符串有占这么大空间吗?程序其他部分都停止运行了,不存在其他消耗内存的东东了,这是为什么?
TStringList中包括一个称为FList的指针,其类型为Point Of TStringItem,而TStringItem这个类型的定义为
TStringItem = record
FString: string;
FObject: TObject;
end;
该结构体最小需要占8个额外的字节。
此外,
procedure TStringList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then Delta := FCapacity div 4 else
if FCapacity > 8 then Delta := 16 else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;
表明TStringList的最大可能会有1/4的空余容量多出来,也就是说,LZ分配的500个String,其实开在内存中的结构可能是650个。
但是这一点差异应当不足以成为内存占用增加4~5M的理由。
所以会不会是idhttp来抓链接的过程中发生了内存泄露状况,譬如说PChar没有释放掉之类的?或者是内存碎片太多?
var
stream,outstream : TMemoryStream;
decomp : TIdCompressorZLibex;
resp : TStringlist;
begin
try
stream := TMemoryStream.Create;
resp := TStringList.Create;
idh.Request.CustomHeaders.Text :=scookie;
idh.Get(url,stream);
stream.Position := 0;
if AnsiCompareText('gzip',idh.Response.ContentEncoding) = 0 then
begin
try
decomp := TIdCompressorZLibex.Create(nil);
outstream := TMemoryStream.Create;
decomp.DecompressGZipStream(stream,outstream);
outstream.Position := 0;
resp.LoadFromStream(outstream);
finally
freeandnil(decomp);
freeandnil(outstream);
end;
end
else
resp.LoadFromStream(stream);
Result := resp.Text;
idh.Disconnect ;
freeandnil(stream);
freeandnil(resp);
except
idh.Disconnect ;
freeandnil(stream);
errorflag:=1;
freeandnil(resp);
end;
end;
另一方面,新的内存块未必就是你给他那么大,他有一个对齐方式.比如4KB对齐.你不停的分配,实际上会产生比较多的碎块.
还有内存管理器管理的时候每个内存块都会有一个描述信息.Delphi的默认是用链表管理的.大量的小块数据就会产生比较多的链表节点,每个节点再有一点描述信息.当然会大.VC一般是放在负偏移有一个描述块,结果是一样的.