Delphi 10.3 Rio - Нужна ли инициализация встроенных объявленных переменных записи? - PullRequest
0 голосов
/ 04 марта 2019

Я очень рад объявлению встроенных переменных Delphi 10.3 Rio.Однако я столкнулся со странной проблемой, и кажется, что мне нужно инициализировать запись после того, как она была объявлена ​​inline:

program Project8;
{$APPTYPE CONSOLE}
{$R *.res}

uses System.SysUtils,classes;

procedure DoEvil;
  //var sr:TSearchRec; //A
begin
  //var sr:= default(TSearchRec); //B
  var sr:TSearchRec; //C
  sr.Name := EmptyStr; //D
  FindFirst('*.*',faAnyFile,sr);
  while sr.Name<>EmptyStr do
  begin
    Writeln(sr.name);
    sr.Name := EmptyStr;
    FindNext(sr);
  end;
end;

begin
  try
     DoEvil;
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

Код работает нормально, если я объявляю sr в строке:

  • // A (объявление старого стиля) или в строке
  • // B (встроенное объявление с инициализацией).

Однако, если я объявляю sr в строке

  • // C, то происходит сбой в строке // D, соответствующей в system.pas в строке 26222:

    MOV     ECX,[EDX-skew].StrRec.refCnt    { fetch refCnt                 }
    

с исключением:

Исключительный класс $ C0000005 с сообщением «нарушение прав доступа в 0x0040ac98: чтение адреса 0xfffffff9».Процесс Project8.exe (18928)

Я бы предположил по адресу -6, что строковый член sr.name не инициализирован и равен nil.

Просто для завершения,Delphi - это новый 10.3 выпуск 1: Embarcadero® Delphi 10.3 Версия 26.0.33219.4899 - Установленное обновление 1

1 Ответ

0 голосов
/ 04 марта 2019

Я заглянул в окно CPU и обнаружил несколько странностей.

Если я использую var-block старого стиля (ваша версия // A), в окне CPU отображается вызов System._InitializeRecord, как это должно.Все нормально и нормально.

Если я использую встроенное объявление с Default() (ваша версия // B), локальная запись обнуляется, затем завершается с использованием System._FinalizeRecord, а затем обнуляется еще раз .Это довольно странно и бесполезно, но это работает.

Но если я использую вашу версию // C, , то ничего не будет сделано для инициализации записи: 1016 *: ничего не вышло, нет _InitializeRecord.Когда я тестировал ваш код, все работало, но мне, вероятно, просто повезло.

Так что это явно ошибка .Пожалуйста, сообщите об этом на Embarcadero Quality Portal .


I думаю это остаток изменений, внесенных в компилятор, когда конструкторы по умолчанию,деструкторы по умолчанию и перегруженные операторы присваивания были протестированы (но затем удалены и отложены до следующего выпуска).Некоторые из этих изменений были скорее мозговыми (например, обнуление, завершение и повторное обнуление, как в версии B), и я думаю, что некоторые из этих изменений были забыты.

Обновление

Очевидно,QP уже сообщал:

...