【问题标题】:How writing to MemoryStream has changed in Delphi 10.2?Delphi 10.2 中对 MemoryStream 的写入发生了哪些变化?
【发布时间】:2018-11-29 08:38:24
【问题描述】:

我正在将我的代码从 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);

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

【问题讨论】:

标签: delphi memorystream delphi-10.1-berlin delphi-10.2-tokyo


【解决方案1】:

您问题中的代码确实在旧版本中编译,但它不应该编译。 10.2 中看到的行为是正确的。

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

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

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

现在恰好TBytes 变量是数组第一个元素的地址。并且 TBytes 覆盖 TMemoryStream.Write 中的任何内容都没有引用该虚假 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;

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

【讨论】:

    【解决方案2】:

    也许什么都没有改变。

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

    您可能不小心将这些方法与使用 typed 参数且 overloaded versions 之一获取 Pointer 类型参数的 Read/WriteData 方法混淆了。

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

    【讨论】:

    • 我没有使用变量的地址,我使用的是数组中第一个元素的地址。这在 Delphi 10.1 中有效。为什么 10.2 在编译时返回错误而 10.1 没有?
    • write方法中使用第一个字节的地址不正确。这是不正确的。简单示例:PByte pb := @CFourBytes[0]; LStream.Write(pb, 4); 并检查您阅读的内容(如果没有出现 AV)。你确定这不是像PChar(@s[1])^ 这样的动态数组/字符串用法吗?您能否显示在西雅图可以正常工作的确切代码?
    • 我们需要澄清一些事情:首先,我使用的是柏林的 10.1,而不是西雅图。第二:我给了你完全工作的确切代码:) 我想,它归结为编译器如何解释代码,它甚至可能是 10.1 中的错误行为,它已在 10.2 中修复。这可以解释为什么在 10.2 编译期间会发出错误
    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多