Issues
您遇到的问题与字符串的引用计数有关。
Leaks
If您要覆盖的区域中已经有一个字符串,这些字符串将不会被释放。这些是您报告的泄漏。
潜在的访问违规
您复制字符串指针,但不会增加字符串的引用计数。如果原始字符串由于超出范围而被破坏,这将导致访问冲突。这是一个非常微妙的错误,会在您最意想不到的时候咬您。
最佳解决方案
让 Delphi 进行复制,然后所有内部簿记都会正确完成,这要简单得多。
{move 6 from cell 1 to cell 3}
System.Move(Array1[0], Array1[3], 2 * SizeOf(string));
//This does not increase the reference count for the string;
//leading to problems at cleanup.
Array1[3]:= Array1[0];
Array1[4]:= Array1[1]; //in a loop obviously :-)
//this increases the reference count of the string.
请注意,Delphi 不会复制字符串,它只是复制指针并根据需要增加引用计数。它还根据需要释放任何字符串。
黑客解决方案
您应该先手动清理该区域。
Using
for i:= start to finish do Array1[i]:= '';
这个解决方案可怕的黑客的下一部分是手动增加您复制的字符串的引用计数。
See: http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats#Long_String_Types http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats#Long_String_Types
procedure IncreaseRefCount(const str: string; HowMuch: integer = 1);
var
Hack: PInteger;
begin
Hack:= pointer(str);
Dec(Hack,2); //get ref count
Hack^:= AtomicIncrement(Hack^,HowMuch);
end;
System.Move(Array1[0], Array1[3], 2 * SizeOf(string));
IncreaseRefCount(Array1[3]);
.... do this for every copied item.
请注意,如果您从数组外部的某个位置获取字符串,则此 hack 不是完全线程安全的。
但是,如果您确实需要速度,那么这可能是使副本性能提高 2% 的解决方案。
Warning
不要使用此代码手动减少引用计数,您将遇到线程安全问题!
需要速度
仅仅处理几个字符串不太可能导致速度变慢。
如果您坚持使用托管字符串,则无法解决清理问题。
另一方面,引用计数的开销实际上并没有那么糟糕,所以我怀疑缓慢的原因在于其他地方;在我们看不到的地方,因为您没有告诉我们您的问题。
我建议你问一个新问题,解释你想要做什么,为什么以及缓慢对你造成了伤害。