Delphi 10.3 Rio - нужна ли инициализация встроенных переменных записи?

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

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 не инициализирован и равен нулю.

Напоминаем, что Delphi представляет собой новую версию 10.3 Release 1: Embarcadero® Delphi 10.3 Version 26.0.33219.4899 - Установленное обновление 1


person Radek Hladík    schedule 04.03.2019    source источник
comment
Я использовал именно тот код, который вы представили выше. Работает без сбоев. Как я уже сказал: Embarcadero® RAD Studio 10.3 Версия 26.0.33219.4899. Цели: 32-битная и 64-битная Windows. Я пробовал все 3 варианта: 1) старый блок var, 2) встроенный с Default и тот, который вы разместили выше, т.е. 3) встроенный, но без инициализации. Все три работают одинаково хорошо.   -  person Rudy Velthuis    schedule 04.03.2019
comment
Я предполагаю, что что-то пошло не так с вашей установкой. Но иногда помогает скопировать код в совершенно новое консольное приложение. Обычно это возможно для таких простых тестовых проектов. И перезагрузите компьютер, прежде чем продолжить. У меня возникли проблемы с недавно установленным Delphis. Обычно помогал перезапуск.   -  person Rudy Velthuis    schedule 04.03.2019
comment
FWIW, у меня были проблемы с компилятором (совершенно плохая генерация кода), когда были установлены некоторые сторонние инструменты. Это обычная ванильная установка (т.е. без сторонних пакетов)?   -  person Rudy Velthuis    schedule 04.03.2019
comment
Попробую завтра на компьютере колледжа. Но я сделал новый проект для этого, так как заметил поведение в другом, более крупном проекте. Установлены только аддоны - это альфа-элементы управления и cnpack.   -  person Radek Hladík    schedule 04.03.2019
comment
Обратите внимание, что происходит утечка, если FindFirst возвращает 0. В этом случае вам нужно будет вызвать FindClose после цикла.   -  person LU RD    schedule 04.03.2019
comment
@LURD Я вырезал код до минимума, чтобы продемонстрировать проблему, но спасибо за ваш комментарий   -  person Radek Hladík    schedule 04.03.2019
comment
Хммм ... Может быть, мне просто повезло. Если я использую старый блок var, вызывается System._InitializeRecord. Если я использую вашу // C строку, это не так. Так что, вероятно, в моем случае это ноль, а в вашем случае это не так. Если я введу код в окне ЦП, я получу вашу ошибку. Похоже, это все-таки ошибка, и мне просто повезло   -  person Rudy Velthuis    schedule 04.03.2019
comment
Вы также используете неправильное условие в вашем while, fwiw.   -  person MartynA    schedule 04.03.2019
comment
Неинициализированные переменные @rudy имеют неопределенное состояние. Они могут быть нулевыми   -  person David Heffernan    schedule 04.03.2019
comment
@ Дэвид: Я знаю. Как я уже сказал: мне повезло.   -  person Rudy Velthuis    schedule 04.03.2019
comment
@rudy Вот почему вы никогда не должны рассматривать один успех как доказательство правильности кода при работе с неопределенным поведением.   -  person David Heffernan    schedule 04.03.2019
comment
@ Дэвид: в чем проблема? А какое неопределенное поведение? Предполагается, что строки в записях инициализируются. Другими словами: код был правильным. Но компилятор неисправен.   -  person Rudy Velthuis    schedule 04.03.2019
comment
@Rudy Да, компилятор неисправен. Из-за этого поведение не определено.   -  person David Heffernan    schedule 04.03.2019
comment
Ну да, каждая ошибка в компиляторе или RTL может вызвать неожиданное поведение. Но в компьютерном программировании неопределенное поведение (UB) является результатом выполнения компьютерного кода, поведение которого не предписано спецификацией языка, которой придерживается код (Википедия). Спецификация языка требует, чтобы каждая строка была инициализирована. Так что это не было неопределенным поведением. Опять же, в чем твоя проблема?   -  person Rudy Velthuis    schedule 05.03.2019
comment
FWIW, если я программирую, я предполагаю, что компилятор не содержит ошибок, и я не проверяю постоянно какие-либо ошибки в компиляторе. Только если что-то пойдет не так, и я уверен, что не допустил ошибки и запрограммировал в соответствии со спецификацией, я начинаю думать об ошибке в компиляторе, а не в моем коде.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@Rudy Ну, UB - это не официальный термин Delphi. Здесь я использую это свободно. Ошибка компилятора приводит к неинициализированной строковой переменной. Я хочу сказать, что ваше успешное выполнение кода абсолютно не свидетельствует о том, что переменная была инициализирована. И когда вопрос явно указывает на ошибку компилятора, я не исключаю этого.   -  person David Heffernan    schedule 05.03.2019
comment
@David: Я хочу сказать, что ваше успешное выполнение кода абсолютно не свидетельствует о том, что переменная была инициализирована. Думаю, поэтому я сказал, что мне повезло.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@Rudy Я действительно изо всех сил пытался понять ваш первый комментарий. Вопрос четко спрашивает, правильно ли инициализирована переменная при объявлении встроенным. И ваш комментарий просто не вяжется с этим. Это все.   -  person David Heffernan    schedule 05.03.2019
comment
Моим первым комментарием было то, что я не могу его воспроизвести. Что ж, это действительно так. Но поскольку я подозревал, что пост был сделан не напрасно и код выглядел правильно, я посмотрел дальше и узнал, что я опубликовал.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@Rudy Вы заподозрили неправильную установку, что довольно забавно. К сожалению, при низком качестве разработки и тестирования Emba ошибка компилятора была очевидным объяснением.   -  person David Heffernan    schedule 05.03.2019
comment
@David: это почти наверняка результат очень краткосрочного отзыва кода управляемой записи. Дерьмо бывает. В отличие от вас, я не считаю, что R&D и QA Embarcadero имеют низкое качество.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@Rudy Удаление основной разработки и введение в последнюю минуту ошибки, которая не была обнаружена из-за недостаточного тестирования, в значительной степени является словарным определением процесса низкого качества.   -  person David Heffernan    schedule 05.03.2019
comment
@David: были веские причины убрать крупную разработку. И да, это было очень в кратчайшие сроки, и это меня сильно разочаровало, но обычно это работает не так, поэтому, на мой взгляд, это была досадная ошибка.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@Rudy Говоря как профессиональный разработчик, исходя из собственного горького опыта, серьезные изменения в последнюю минуту всегда сопряжены с повышенным риском. Процессы хорошего качества призваны избегать и сдерживать эти риски. История плохого качества выпусков на Эмба (по крайней мере, за последние 5 лет) является явным доказательством того, что процесс их обеспечения качества является несовершенным. Сами Эмба это знают, о чем свидетельствуют заявления о том, что они сделают упор на качество. Однако одно дело признать проблему и решить ее, и совсем другое - добиться успеха в ее решении.   -  person David Heffernan    schedule 05.03.2019
comment
@ Дэвид: серьезное изменение в последнюю минуту всегда сопряжено с повышенным риском. Конечно, но иногда у тебя нет выбора.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@RudyVelthuis У тебя всегда есть выбор. Вы можете отложить выпуск до тех пор, пока не закончите тестирование изменения. Вы можете вообще избежать необходимости вносить изменения, объединяя ветвь функций с разработкой только тогда, когда вы уверены, что она готова к выпуску. Так происходит крупномасштабная разработка. Необходимы надежные процессы для поддержки развития. Не оправдывайся за Эмбу. Если они ошибаются, вызовите их. Разве вы не MVP? Вы должны использовать это, чтобы говорить правду власти.   -  person David Heffernan    schedule 05.03.2019
comment
Каждый раз, когда я вижу, что кто-то пишет «У тебя всегда есть выбор», я съеживаюсь. Нет, у вас не всегда есть (жизнеспособный) выбор.   -  person Rudy Velthuis    schedule 05.03.2019
comment
@RudyVelthuis Есть оправдание.   -  person David Heffernan    schedule 05.03.2019
comment
@ Дэвид: во-первых, я думаю, что это бесполезное обсуждение, а во-вторых: а?   -  person Rudy Velthuis    schedule 05.03.2019
comment
У Delphi много проблем с IDE, которые существуют годами или даже десятилетием, и сгенерированный код иногда не эффективен, как мог бы быть, но, с другой стороны, это Паскаль, он может компилироваться для многих платформ, дизайн пользовательского интерфейса прост и понятен. .. Итак, я пытаюсь сказать, что каждый разработчик должен знать свои инструменты и выбирать их соответственно. И, честно говоря, Delphi во многом улучшилась. Я все еще использую Delphi 6 (6 не XE6) для одного проекта, и разница огромна. Но эта версия Delphi по-прежнему работает на Win7 и производит код, работающий на Win2016 ... Так что хорошо, Borland ..   -  person Radek Hladík    schedule 05.03.2019


Ответы (1)


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

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

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

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

Значит, это явно ошибка. Сообщите об этом на Портал качества Embarcadero.


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

Обновлять

Очевидно, об этом уже было сообщено QP:

person Rudy Velthuis    schedule 04.03.2019
comment
Уже зарегистрировано как: quality.embarcadero.com/browse/RSP-21632 quality.embarcadero.com/browse/RSP-23417 quality.embarcadero.com/browse/RSP-23747 - person Stefan Glienke; 04.03.2019
comment
Assert(sr.Name = '','sr not initialized'); - это быстрый способ проверить ошибку в режиме отладки. - person LU RD; 04.03.2019
comment
@LURD: конечно, но если вам повезет, как и мне, это тоже не найдет проблемы. Нынешний путь был так же уверен, что его найдешь. Мне повезло, и это сработало. Но теперь, чуть позже, я получаю ту же ошибку, что и OP. - person Rudy Velthuis; 04.03.2019
comment
Может помочь, если перед вызовом стек будет зашифрован. В любом случае, немного разочаровывает, что такая ошибка могла проскользнуть через релиз. Это было бы первым делом для тестирования на модульном тесте. - person LU RD; 04.03.2019
comment
@LURD Я дождался первого обновления после того, как они внесли такое серьезное изменение синтаксиса. И мне кажется забавным, что даже сейчас средство проверки синтаксиса в редакторе не понимает этот новый синтаксис - но это только неудобство во время разработки. Однако создание кода, который случайно дает сбой, является серьезной проблемой. Тем более, что основная причина, по которой я взволнован этой функцией, - это ограничение объема переменных и, таким образом, уменьшение количества ошибок :-) - person Radek Hladík; 05.03.2019
comment
@Radek: Я предполагаю, что у них будет соответствующее обновление и для компилятора. Но я думаю, разобраться с компилятором не так-то просто. - person Rudy Velthuis; 05.03.2019
comment
@ RadekHladík, Я медленный адаптер, но тестировщик рано. Добавление новых языковых функций к существующему коду опасно. - person LU RD; 05.03.2019
comment
@LURD на 100% согласен. Я тестировал это на одном экспериментальном проекте для собственного использования, и эта функция действительно великолепна :-) С другой стороны, она делает код обратно несовместимым и несовместимым с FreePascal .... - person Radek Hladík; 05.03.2019