在我的项目中,字符串“内存不足异常”存在问题,未使用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.如何避免内存不足?
内存不足错误来自内存碎片。
因此,上一个问题的两个解决方案将解决此问题。