在Delphi10.2中,对MemoryStream的写入发生了怎样的变化



我正在将代码从10.1移植到10.2,这给了我错误:

procedure TForm4.FormCreate(Sender: TObject);
const
CFourBytes: array[0..3] of Byte = (1, 2, 3, 4);
var
LStream: TMemoryStream;
LBuffer: array of Byte;
begin
SetLength(LBuffer, 4);
LStream := TMemoryStream.Create;
LStream.Write(@CFourBytes[0], 4); // E2036 Variable required
LStream.Position := 0;
LStream.ReadData(@LBuffer[0], 4);
end;

我不得不将违规线路更改为LStream.Write(CFourBytes[0], 4);

发生了什么变化?我一直都做错了吗?

问题中的代码确实是在旧版本中编译的,但不应该这样做。10.2中的行为是正确的。

旧版本中发生的事情非常奇怪。编译器在TStream:中选择此重载

function Write(const Buffer: TBytes; Count: Longint): Longint; overload;

这尤其令人震惊,因为传递给该方法的是静态数组CFourBytes的地址。它绝对不是TBytes对象。

现在恰好TBytes变量是数组第一个元素的地址。TMemoryStream.WriteTBytes覆盖中没有任何内容引用该伪TBytes对象的Length()。因此,您的代码恰好按预期工作。这显然是一个已经修复的编译器错误。

你的代码总是被破坏,到目前为止,你只是幸运地逃脱了惩罚。你应该修复你的代码。像这样:

LStream := TMemoryStream.Create;
try
LStream.WriteBuffer(CFourBytes, SizeOf(CFourBytes));
SetLength(LBuffer, LStream.Size);
LStream.Position := 0;
LStream.ReadBuffer(LBuffer[0], LStream.Size);
finally
LStream.Free;
end;

请注意,我使用的是WriteBufferReadBuffer,而不是WriteRead。这些是与TStream一起使用的首选方法。原因是它们执行错误检查,并在出现错误时引发异常,这与WriteRead不同。

也许什么都没有改变。

TStream.Write/Read方法总是使用未类型化的const/var参数const Buffer(help(,并且使用变量的地址是错误的(因为方法(确切地说是编译器(找到变量本身的地址(。

您可能不小心将这些方法与使用类型参数的读/写数据方法混淆,并且其中一个重载版本获得Pointer类型参数。

这里,ReadData实现取消引用该指针并在内部使用Read(Read依次调用Move,最后一个例程再次获得缓冲区地址:(

相关内容

最新更新