【发布时间】:2016-05-03 08:34:04
【问题描述】:
编译器在使用函数时为shortstring生成了错误的代码
function TTestObject<T>.Compare(const Left, Right: T): integer; inline;
它会破坏参数。
下面的示例程序演示了这个概念:
program ShortStringsAndConst;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TStr100 = string[100];
TTestObject<T> = class
private
Bag1, Bag2: T;
procedure RandomBags;
procedure TestCompare;
function CompareFail(const Left, Right: T): integer; inline;
function CompareWin(const [ref] Left, Right: T): integer; inline;
end;
var
TestStr100: TTestObject<TStr100>;
procedure Test;
begin
TestStr100:= TTestObject<TStr100>.Create;
TestStr100.RandomBags;
TestStr100.TestCompare;
end;
{ TTestObject<T> }
procedure TTestObject<T>.RandomBags;
var
a: integer;
begin
PByteArray(@Bag1)^[0]:= SizeOf(T)- 1;
for a:= 1 to SizeOf(T)- 1 do begin
PByteArray(@Bag1)^[a]:= byte('a');
end;
Bag2:= Bag1;
end;
function TTestObject<T>.CompareFail(const Left, Right: T): integer;
var
L,R: shortstring;
begin
L:= PShortstring(@Left)^;
R:= PShortstring(@Right)^;
WriteLn(Format('Fail!! @Left = %p, @Right = %p, Left = %s, Right = %s',[@Left, @Right, L, R]));
end;
function TTestObject<T>.CompareWin(const [ref] Left, Right: T): integer;
var
L,R: shortstring;
begin
L:= PShortstring(@Left)^;
R:= PShortstring(@Right)^;
WriteLn(Format('Win: @Left = %p, @Right = %p, Left = %s, Right = %s',[@Left, @Right, L, R]));
end;
procedure TTestObject<T>.TestCompare;
begin
CompareFail(Bag1,Bag2);
WriteLn;
CompareWin(Bag1,Bag2);
ReadLn;
end;
begin
Test;
end.
问题
假设我可以在泛型函数中使用普通的const 是我的错误,还是这是一个编译器错误?
额外问题
除了 Shortstring,还有其他类型会导致 CompareFail 生成无效代码吗?
背景
我觉得没有强烈需要使用shortstring,但我正在编写一些通用库代码并且需要支持所有类型。
更新 这是一个编译器错误,已在 10.1 Berlin 中修复。
【问题讨论】:
-
你为什么要使用
[ref]。这只会导致代码变慢。 -
@DavidHeffernan 因为不使用
[ref]会导致代码无法正常工作:-(。不过我没有注意到速度上的差异,将仔细检查。 -
声明为
CompareFail(var Left, Right: T): integer; inline;有效。 -
哦,我明白了。这是一个错误。
-
@LURD,是的,除了你在长字符串上得到的 try-finally 和 ref-counting。所以这算不上胜利。
标签: delphi generics inline-code compiler-bug