Как изменилась запись в MemoryStream в Delphi 10.2? - PullRequest
0 голосов
/ 29 ноября 2018

Я портирую свой код с 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);

Что изменилось?Я делал это неправильно все время?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Код в вашем вопросе компилировался в более старых версиях, но этого не должно было быть.Поведение в версии 10.2 является правильным.

То, что происходит в старых версиях, очень странно.Компилятор выбирает эту перегрузку в TStream:

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

Это особенно вопиюще, поскольку в этот метод передан адрес статического массива CFourBytes.Который категорически не является TBytes объектом.

Теперь просто так получается, что переменная TBytes является адресом первого элемента массива.И ничто в переопределении TBytes для TMemoryStream.Write не относится к Length() этого поддельного TBytes объекта.Таким образом, ваш код работает так, как задумано.Совершенно очевидно, что эта ошибка компилятора была исправлена.

Ваш код всегда был взломан, вы до сих пор просто удалялись от него по случайности.Вы должны исправить свой код.Например:

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.

0 голосов
/ 29 ноября 2018

Возможно, ничего не изменилось.

TStream.Write/Read методы всегда использовали нетипизированный const/var параметр const Buffer ( help ) и использование адреса переменной неверно (потому что метод (дляточнее - компилятор) находит адрес самой переменной).

Возможно, вы случайно путаете эти методы с методами чтения / записи Data , которые используют типизированный параметр и один из перегруженные версии получает Pointer аргумент типа.

Здесь ReadData реализация разыменовывает этот указатель и использует Read внутренне (Read в свою очередь вызывает Move, и последняя подпрограмма снова получает адрес буфера :))

...