【发布时间】:2012-10-11 10:08:16
【问题描述】:
在 Delphi 函数中,结果经常被实现为 var-parameter(尽管有 QC 票,但不是 out-parameter)。
字符串常量基本上是具有负引用计数器的变量,应该抑制自动内存[de]分配。 http://docwiki.embarcadero.com/RADStudio/XE3/en/Internal_Data_Formats#Long_String_Types
它确实抑制了它:下面的代码没有泄漏。
type
TDealRecord = record
id_Type: Integer;
Price: extended;
Remark: String;
end;
const const_loop = 100000000;
function TestVar: TDealRecord;
//procedure TestVar;
var
Li: Integer;
LRec: TDealRecord;
begin
for Li := 1 to const_loop do begin
FillChar(Lrec,SizeOf(LRec), 0);
LRec.Remark := 'Test';
// FillChar(Result,SizeOf(Result), 0);
// Result.Remark := 'Test';
end;
end;
但是改变操纵变量 - 它立即开始大量泄漏。
function TestVar: TDealRecord;
//procedure TestVar;
var
Li: Integer;
LRec: TDealRecord;
begin
for Li := 1 to const_loop do begin
// FillChar(Lrec,SizeOf(LRec), 0);
// LRec.Remark := 'Test';
FillChar(Result,SizeOf(Result), 0);
Result.Remark := 'Test';
end;
end;
原来string := const是用不同的调用实现的,具体取决于LValue:
- 结果:AnsiString -> LStrAsg
- 结果:UnicodeString:-> UStrAsg
- 本地变量:UnicodeString:-> UStrLAsg
- 本地变量:AnsiString:-> LStrLAsg
虽然后两者按预期克隆指针,但前两者将字符串复制到新实例,就像我向它们添加 UniqueString 调用一样。
为什么会有这种差异?
【问题讨论】:
-
这可能是由于具有局部范围的变量和具有在其中进行赋值的函数之外的范围的变量之间的差异。当您分配给
Result变量时,您正在分配一个在该函数之外可见的变量。当您分配给本地时,它是该函数私有的。 -
@David,是的,是的,但是“那又怎样?” !为什么禁止将外部变量指向“-1”常量?当(如果)需要时,它将按需分开。并且在函数中主动执行它看起来像是过早的优化,并且当“常识”没有区别时也会引入完全不同的行为。
-
我只能认为编译器无法跟踪它分配“来自”的内容。它认为它分配的不是全局常量,而是堆栈上的内部表达式,这将丢失。然后立即克隆是有意义的。但这似乎太粗糙了,如此“全局”的规则以至于效率相当低。
标签: string delphi delphi-xe2 refcounting