-->

使用AnsiString类型象在Delphi XE4阵列的字节(Using AnsiString l

2019-10-19 02:55发布

试图移动Delphi 2007项目XE4 。 在Delphi 2007我用函数读取使用从插座字节数组Indy直接。 我通过AnsiString强制转换为字节给这个函数的变量参数数组:

var data:AnsiString;
AContext.Connection.IOHandler.ReadBytes(TIDBytes(Data), PacketLength-PacketLengthDelta-1, False);

Dlphi XE当我尝试concatinate Data到另一个字符串我access violation错误。

现在,我试图模拟更简单的代码这个问题:

TIdBytes = array of Byte;

procedure fill(var b: TIDBytes);
begin
setlength(b,5);
b[0]:=61;
b[1]:=61;
b[2]:=61;
b[3]:=61;
b[4]:=61;

//original function used move function
end;



procedure TMainForm.FormCreate(Sender: TObject);
var s: ansistring ;
begin
fill( TIDBytes(s) );
Showmessage(s);
end;

现在,我希望看到类似====消息框,但我得到了空单。 我假设XE AnsiString类型就像2007年德尔福AnsiString类型相同,你可以使用他们喜欢在这两种情况下字节数组。

什么是解决问题的字节填充AnsiString类型的最好方法?

Answer 1:

这是从来没有有效投的AnsiString为一个字节数组。 该代码(这取决于你的观点或倒霉的)总是坏,你真的很幸运。

管理字符串类型,就像动态数组,具有信息,元数据,即刚好在数据有效载荷之前存储的额外的有效载荷。 该元数据包括参考计数,长度等,但字符串中的元数据是不一样的,作为动态数组。 简单地说,一个字符串是不是一个动态数组。 您重新解释投是完全无效的。 这是在旧版本的Delphi无效的,它只是在现代版本为无效。

到底发生了什么引擎盖下是元数据的规模已经引进的Unicode支持改变。 对于元数据AnsiString已经扩大。 现在,它包含,例如,字符串的代码页。

现在,当你调用SetLength ,内存足够大的元数据和有效载荷的块被分配。 假设存储器在地址P分配,你的变量(字符串或动态数组)持有被设置为P +元数据尺寸的地址。 当你来到解除分配对象,系统运行至P -元数据的大小,并调用FreeMem与该地址。 而这里的起脚。 如果取消分配可以使用,当你分配一个动态数组元数据的大小,而是一个字符串的大小元数据。 结果? 繁荣! 你刚才叫FreeMem上一个无效的地址,尚未分配给你一个。

以正确的操作方法是给印地功能它想要的东西。 即一个字节数组。 如果您需要转移到一个字符串变量,字节数组的内容复制到一个新的字符串。 例如使用TEncoding.Default.GetString()



Answer 2:

使用您的填充过程和你的TIDBytes定义:

procedure Test;
var
  s: ansistring;
  b: TIDBytes;
begin
  fill(b);
  s := StringOf(TArray<byte>(b));
  ShowMessage(s);
end;

PS:@大卫的答案是正确的,但你可以使用directy的字节数组,然后使用StringOf得到串/ AnsiString类型



文章来源: Using AnsiString like byte of array in Delphi XE4