Как я должен подготовить свои 32-разрядные программы Delphi для возможного 64-битного компилятора?

Возможный дубликат:
Как подготовиться к 64-битам при переходе на Delphi 2010 и Unicode

Поскольку я считаю, что компилятор Delphi 64 бит появится в ближайшее время, Мне любопытно, если кто-нибудь знает, какие программы которые теперь 32bit будут компилироваться и работать без каких-либо изменений при использовании 64-битного компилятора.

И если есть общее правило, какие изменения должны мы систематически делать в наших старых программах для компиляции как 64bit?

Хорошо быть готовым, когда компилятор 64bit будет внезапно здесь...

Любое предложение будет высоко оценено.

Ответ 1

Прежде всего, отказ от ответственности: хотя я работаю на Embarcadero. Я не могу говорить за своего работодателя. То, что я собираюсь написать, основано на моем собственном мнении о том, как должна работать гипотетическая 64-разрядная Delphi, но могут быть или не быть конкурирующие мнения и другие предусмотренные или непредвиденные несовместимости и события, которые вызывают альтернативные дизайнерские решения.

Это сказало:

  • Существует два целочисленных типа: NativeInt и NativeUInt, размер которых будет плавать между 32-битными и 64-битными в зависимости от платформы. Они были вокруг довольно много выпусков. Никакие другие целочисленные типы не изменят размер в зависимости от битности цели.

  • Убедитесь, что в любом месте, которое полагается на значение указателя, integer или наоборот использует NativeInt или NativeUInt для целого числа тип. TComponent.Tag должен быть NativeInt в более поздних версиях Delphi.

  • Я бы предложил не использовать NativeInt или NativeUInt для значений, не содержащих указателей. Постарайтесь, чтобы ваш код семантически совпал между 32-битным и 64-битным. Если вам нужно 32 бита диапазона, используйте Integer; если вам нужны 64 бита, используйте Int64. Таким образом, ваш код должен работать одинаково на обеих битах. Только если вы используете значение типа указателя какого-либо типа, например ссылку или THandle, следует использовать NativeInt.

  • Используйте PByte для арифметики указателя, где это возможно, вместо NativeInt или NativeUInt. Этого достаточно для большинства целей и более типично, потому что его нельзя (легко) ошибочно принять за обычный целочисленный тип и наоборот.

  • Пойнтер-подобные вещи должны следовать аналогичным правилам указателям: объект (очевидно), но также такие вещи, как HWND, THandle и т.д.

  • Не полагайтесь на внутренние детали строк и динамических массивов, например их данные заголовка.

  • Наша общая политика по изменениям API для 64-разрядной версии должна состоять в том, чтобы сохранить один и тот же API между 32-битными и 64-битными, если это возможно, даже если это означает, что 64-битный API не обязательно использует машину. Для Например, TList, вероятно, будет обрабатывать MaxInt div SizeOf (Pointer) элементов, чтобы сохранить Count, индексы и т.д. как Integer. Поскольку Тип Integer не будет плавать (т.е. Изменить размер в зависимости от битности), мы не хотят иметь волновой эффект на код клиента: любые индексы, которые round-tripped через переменную типа Integer или индекс for-loop, будет усекаться и потенциально вызвать тонкие ошибки.

  • Если API-интерфейсы расширены для 64-разрядных, они, скорее всего, будут выполнены с помощью дополнительную функцию/метод/свойство для доступа к дополнительным данным, и это API также будет поддерживаться в 32-разрядной версии. Например, стандарт Length() процедура, вероятно, вернет значения типа Integer для аргументов тип строки или динамический массив; если кто-то хочет иметь дело с очень большими динамических массивов, может быть и процедура LongLength(), чья реализация в 32-бит такая же, как Length(). Длина() будет бросать исключение в 64-битном случае применяется к динамическому массиву с более чем 2 ^ 32 элементы.

  • В связи с этим, вероятно, будет улучшена проверка ошибок для сужение операций на языке, особенно сужение 64-битных значений до 32-разрядных местоположений. Это повлияло бы на удобство назначения возвращаемое значение Length для местоположений типа Integer, если Length(), вернулся Int64. С другой стороны, специально для компилятора-магии функции, такие как Length(), может быть какое-то преимущество магии, например, переключите тип возврата на основе контекста. Но преимущество не может быть аналогично взяты в не магических API.

  • Динамические массивы, вероятно, поддерживают 64-битную индексацию. Обратите внимание, что Java массивы ограничены 32-разрядной индексацией даже на 64-битных платформах.

  • Строки, вероятно, будут ограничены 32-разрядной индексацией. У нас есть время придумывает реалистичные причины для людей, желающих 4GB + строки это действительно строки, а не только управляемые капли данных, для которых динамические массивы могут также служить.

  • Возможно, встроенный ассемблер, но с ограничениями, например, неспособный свободно смешивать с кодом Delphi; существуют также правила вокруг исключений и макета фрейма стека, которые должны соблюдаться на x64.

Ответ 2

Прежде всего, FreePascal уже предлагает поддержку 64-битных. Однако это не Delphi.
Во-вторых, я ожидаю, что те же проблемы, которые существовали в то время, когда Delphi 1 был обновлен до Delphi 2. Самая большая проблема заключается в основном в адресном пространстве, и проблема в том, что указатели будет увеличена с 4 до 8 байтов. В WIN16 они используются как 2 байта, и для достижения границы 64 КБ необходим трюк, используя сегменты и смещения для указателей. (С возможностью использования сегментов по умолчанию для нескольких задач.)
Вероятно также, что некоторые типы данных станут больше, чем сейчас. Скорее всего, будет целочисленный тип 8 байтов. (В Windows 2 используется только 2 байта). Перечисления, скорее всего, тоже станут больше. Но большинство других типов данных, скорее всего, сохранят свой текущий размер, поэтому здесь не так уж много изменений.
Еще одна проблема - требования к памяти. Поскольку указатели будут иметь длину 8 байтов, приложение, использующее многие из них, также будет потреблять намного больше памяти. Список с 10.000 указателями будет увеличен с 40.000 байт до 80.000 байт. Возможно, вы захотите использовать немного больше памяти, чем в 32-битной системе.
Скорость также немного изменится. Поскольку процессор теперь обрабатывает 8 байтов одновременно, он может обрабатывать данные намного быстрее. Но поскольку указатели и некоторые типы данных становятся больше, прием или отправка их на какое-либо устройство или память будет немного медленнее. В общем, ваши приложения в целом будут немного быстрее, но некоторые части могут стать медленнее!
Наконец, изменения в Windows API потребуют от вас использовать 64-битные функции API. Может быть, компилятор Delphi сделает что-то умное, чтобы позволить коду вызывать 32-битные функции API, но это снизит производительность, потому что теперь процессор переключается между собственным 64-битным режимом и эмулированным 32-битным режимом.

Ответ 3

В зависимости от вашего кода вы можете попытаться скомпилировать его с помощью FreePascal, который поддерживает как 32-битную, так и 64-битную компиляцию. Компилятор предупредит вас о возможно ошибочных местах вашего кода.

Ответ 4

Было задано много похожих вопросов, когда было объявлено, что Delphi 2009 будет создавать только приложения Unicode. В конце концов выяснилось, что самый существующий код работает нормально, без изменений. Трудные части были кодом, который предполагал, что SizeOf(Char) = 1 и сторонние компоненты, которые могут это делать.

Я бы ожидал, что переход на 64-битный Delphi будет аналогичным. Все просто работает вне коробки, за исключением кода, который играет трюки с указателями и предполагает, что SizeOf(Pointer) = 4 или SizeOf(Pointer) = SizeOf(Integer). Вы уже можете исправить такие проблемы сегодня, вызвав SizeOf(Pointer), а не hardcoding 4 и используя NativeInt или NativeUInt, когда вам нужны целые числа с размером указателя.

Вы должны использовать SizeOf(Pointer), а не SizeOf(NativeInt), если вы хотите, чтобы ваш код работал с Delphi 2007. Delphi 2007 имеет неудачную ошибку, которая заставляет SizeOf(NativeInt) возвращать 8 вместо 4, как следует. Это было исправлено в Delphi 2009.

Ответ 5

Подавляющее большинство простых приложений должно работать нормально. Насколько я вижу, только приложения, которые вручную используют указатели, подвергаются риску. Действительно, если указатель теперь является 64-битным, и вы используете его в вычислениях вместе с целыми числами или кардиналами (которые по умолчанию по-прежнему 32-битные), у вас возникнут проблемы. Я также считаю довольно распространенным, что декларации для функций API, которые принимают указатели в качестве аргументов, используют cardinal вместо (целочисленного) типа (без знака).

Чтобы сделать код, который хорошо работает на любой платформе, следует использовать NativeUInt (IIRC, теперь у меня нет компилятора Deplhi) вместо cardinal при работе с указателями и целыми числами.

Ответ 6

Пока Embarcadero не публикует официальную информацию об их 64-битной реализации, нелегко сказать. Вы должны проверять любые нажатия на/из указателя, Integer и Cardinal, предполагая, что они являются собственными размерами платформы, включая свойства объекта и ссылки (например, сохранение Integer в свойстве TObject, которое является указателем, или использование тега для хранения ссылок, а не цифр).

Вы также должны убедиться, что никакой код не использует эффект "обтекания" при увеличении (или уменьшении) значения в максимальном (минимальном) размере.

Проверьте любой код в структурах, которые зависят от размера данных, и не используют SizeOf() правильно, и в целом, что SizeOf() всегда используется, когда имеет значение data. Проверьте код, который записывает/читает данные в файлы, если размеры могут меняться, особенно если данные необходимо обменять между 32 и 64-битным кодом.

Проверьте изменения Win64, если приложение вызывает API и управляет сообщениями Windows напрямую. Кодированный код ASM должен быть проверен на совместимость с 64 бит (существует гораздо более строгий правило для написания 64-битного ассемблера).

Ответ 7

Помимо очевидных задач указателя ↔ int: (используя intptr/nativeint/ptrint и т.д.)

  • Все, что у вас есть как двоичный blob (DLL, возможно, OCX и т.д.), нужно обновить. Это может включать старые SDK для ключей и т.д.
  • Все инструменты, которые выполняют что-то на двоичном уровне (отладчики, профилировщики, домашние домашние инструменты), могут нуждаться в обновлениях.
  • Необходимо выполнить обновление всех ассемблерных и других очень низкоуровневых трюков (например, в зависимости от компоновки VMT, отладочных форматов (трассировки) динамических загрузочных заглушек, таких как Jedi Apilib и т.д.).
  • проверить все собственные созданные заголовки на предмет изменений в упаковке и mistranslations, которые имеют значение now pointer < > integer. Бланк упаковки не следует недооценивать.
  • Взаимодействие с Office и другими внешними приложениями может измениться
  • TComponent.tag теперь длинный, и, таким образом, может оставаться longint, что означает, что схемы, которые содержат указатели в component.tag, могут не работать.
  • x87 FPU устарел на x64, и в общем случае SSE2 будет использоваться для точки флорирования. поэтому плавающая точка и обработка исключений могут работать несколько иначе, а расширение может быть не 80-битным (но 64-битным или, менее вероятным, 128-битным). Это также относится к обычным изменениям округления (copro controlwork) при взаимодействии с кодом C, который ожидает другое слово fpu.

Укладка проблемы с записями - это то, что я заметил при переносе существующих заголовков на win64.

Ответ 8

Мои 2 цента:

  • в старые времена каждый автор asm должен был нажать ИСПОЛЬЗОВАТЬ BASM

  • внешний asm64 был бы приемлемым, а использование старого кода inlclude xy.obj, в любом случае требуется полная переписывание

  • Отладчик и CPU64: вопрос будет в том, что это еще есть?

  • D64 Float Extended: поддерживается ли это как 80-битный float?

Нр

Ответ 9

Как полная догадка, любой код, который не зависит от определенного размера слова, или может адаптировать его размер слова на основе того, что говорит компилятор, будет в порядке.