string:= const:为什么不同的本地实现和结果? [英] string := const : why different implementation for local and result?

查看:234
本文介绍了string:= const:为什么不同的本地实现和结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



字符串常量基本上是带有反引号的变量,应该是禁止自动记忆[de]分配。 http://docwiki.embarcadero.com/RADStudio/XE3/en/Internal_Data_Formats#Long_String_Types



它确实抑制它:下面的代码不会泄漏。

  type 
TDealRecord = record
id_Type:Integer;
价格:延长;
备注:String;
结束
const const_loop = 100000000;

函数TestVar:TDealRecord;
// procedure TestVar;
var
Li:整数;
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';
结束
结束

但更改操纵的变量 - 它立即开始大量泄漏。

  function TestVar:TDealRecord; 
// procedure TestVar;
var
Li:整数;
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';
结束
结束

原来, string:= const 根据LValue实现不同的通话:


  1. 结果:AnsiString - > LStrAsg

  2. 结果:UnicodeString: - > UStrAsg

  3. 本地var:UnicodeString: - > UStrLAsg

  4. 本地var:AnsiString: - > LStrLAsg

而后两者是按预期的克隆指针,前两者将字符串复制到新的实例,就像我添加 UniqueString 呼吁他们。



为什么会有这样的区别?

解决方案

在与David Heffernan 进行讨论之后,我开始认为Delphi编译器不知道它赋值给变量的值是多少。有类型的擦除的地方。它不能从本地堆栈变量和本地字符串表达式中得出全局常量。在功能退出发生后,它不能确定源是否存在。而我们知道这是字符串字面量或全局常量,或任何与生命周期无关的功能执行 - 编译器只会丢失该信息。相反,它起到防御性的作用,总是克隆价值 - 只是为了不再存在的机会。我不确定,但看起来很合理。虽然这种粗暴的不加区别的代码规则的后果在德尔福还有一个问题: - (


In Delphi function result is frequently implemented as var-parameter (not out-parameter despite QC ticket).

String constants are basically variables with negative refcounter, which should suppress automatic memory [de]allocation. http://docwiki.embarcadero.com/RADStudio/XE3/en/Internal_Data_Formats#Long_String_Types

It really does suppress it: the code below does not leak.

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;

But change the manipulated variable - and it immediately starts to leak heavily.

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;

It turns out that string := const is implemented with different calls, depending on LValue:

  1. Result: AnsiString -> LStrAsg
  2. Result: UnicodeString: -> UStrAsg
  3. Local var: UnicodeString: -> UStrLAsg
  4. Local var: AnsiString: -> LStrLAsg

And while the latter two are cloning pointer as expected, the former two are copying the string to new instance, like if i add UniqueString call to them.

Why that difference ?

解决方案

After discussion with David Heffernan, i am starting to think that Delphi compiler just does not know what is the value it assigns to variable. Kind of "type erasure" having place. It cannot tell global constant from local on-stack variable and local string expression. It cannot tell if the source would exist after function exit happened. while we know that is string literal or global constant or anything with lifetime independent of the function execution - the compiler just loses that info. And instead it plays defensive and always cloning the value - just for the chance that it would cease to exist. I am not sure, but that looks reasonable. Though the consequences of this rough indiscriminate codegen rule are one more gotcha in Delphi :-(

这篇关于string:= const:为什么不同的本地实现和结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆