在我的项目中,字符串“内存不足异常”存在问题,未使用MM。该问题显示字符串的长度何时达到2 300,000个符号。尽管事实上有足够的内存,并且在代码的同一部分中,我仍可以创建具有100,000,000个字符的字符串。

Google没有帮助,我无法将其分解(没有技能),因此我决定创建一个最小的测试示例,在该示例中,我可以在少于2000000000000符号的字符串上摆脱内存异常。我无法创建这样的示例,但是创建了一些陌生人:

program Project2;
{$APPTYPE CONSOLE}
uses
   SysUtils;

var s : string;
    k : integer;

function b : string;
begin
 result := 'f';
end;

procedure c;
var ss : string;
begin
  s := s + '{' +  b + '}';
  ss :=  'a';

  if k mod 100001 = 0 then
  begin
     // ss[1] := 'd';    // uncoment me
     write(k mod 10);
  end;

  inc(k);
end;

begin
  while true do c;
end.


此代码可以正常工作。它只是通过一些额外的操作向全局字符串添加了一些内容。问题是,如果您取消注释标记的字符串,它将大大减慢速度(无论是否优化)。考虑到该赋值每100,001次迭代一次,因此它一定不能放慢速度。

问题:


Delphi中的默认字符串如何工作?
如何避免减速?
如何避免内存不足?


附言如果我将FastMM包含在主项目中,错误将消失
p.p.s带有未注释字符串的示例在3分钟内(从用户模式)将Windows 7发送到BSOD。

最佳答案

1. Delphi中的默认字符串如何工作?

每次受影响时都会分配一个新的string(通过:=)。

那是,

s := s + '{' +  b + '}';


将为string分配s + '{' + b + '}';,然后将其复制到变量s

每次运行此行时,您都有一个内存分配和一个内存释放。即使使用FastMM4,这也可能很慢。但是使用较旧的MM可能会非常缓慢。

2.如何避免减速?

如果您在使用“ Borland”内存管理器的旧Delphi中,则分配和重新分配非常缓慢。而且它将使内存碎片很多。

ss[1] := 'd'当然由于内存碎片而非常慢,并且Borland Memory Manager必须对该行的内存分配进行一些缓慢的清理。

用以下方法更改行:

var ss: string[1];


而且它不会再减慢速度了,因为shortstring将在堆栈上分配,并且不会使用堆。

因此,为了避免速度变慢:


使用现代内存管理器,例如FastMM4;
使用类似TStringBuilder的类,或使用旧的TMemoryStream在其中添加数据:内存重新分配要少得多,因此它会快得多。


3.如何避免内存不足?

内存不足错误来自内存碎片。

因此,上一个问题的两个解决方案将解决此问题。

07-24 09:45
查看更多