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

59

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

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

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

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

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

  • 8
    Назначен для повторного открытия, поскольку этот вопрос, по-видимому, дает бесконечно больше полезных ответов, чем отмеченный дубликат.
  • 3
    С чего вы взяли, что Embarcadero скоро выпустит 64-битный компилятор Delphi?
Показать ещё 3 комментария
Теги:
unicode
32bit-64bit
delphi-2010

9 ответов

76

Прежде всего, отказ от ответственности: хотя я работаю на 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.

  • 17
    Ой, что ни один бит ассемблера не причинит мне большого вреда У меня много SSE-кода в моих приложениях. Да, я знаю, мне, вероятно, придется изменить их, нажав / выдавая регистры в x86_64, но это обновление, чем поиск другого решения.
  • 0
    «Length () выдаст исключение в 64-битной среде, если применить его к динамическому массиву с более чем 232 элементами». Ммм ... 232?
Показать ещё 25 комментариев
8

Прежде всего, 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-битным режимом.

  • 7
    На 64-битной Windows модель предназначена для int и долго остается 32-битной. Соответственно, Delphi будет следовать за Integer, а Longint останется 32-разрядным. Кроме того, в Delphi перечисления всегда имели наименьший тип, способный представлять их диапазон.
  • 0
    С Delphi 1 до Delphi 2 целочисленный тип изменился с 2 байтов до 4. Поскольку это общий целочисленный тип, я ожидаю, что он снова увеличится, хотя Embarcadero может оставить его на 4 байта. В перечислениях будет использоваться наименьший размер, который будет соответствовать всем значениям, но вы можете указать минимальный размер для типов перечисления, используя {$ Z1} или {$ Z2} или {$ Z4} {$ MINENUMSIZE 1} или {$ MINENUMSIZE 2} или {$ MINENUMSIZE 4}. Я думаю, что они могли бы добавить {$ Z8} к этому также. Это связано с (упакованными) записями и их выравниванием полей записей.
Показать ещё 8 комментариев
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.

  • 0
    Я сделал свое преобразование в Unicode довольно быстро, но все равно были
  • 0
    довольно некоторые изменения: все IORoutines (reset, readln, rewrite, writeln) для чтения и записи в файлы больше не работают для Unicode, в каждой процедуре записи строк должен быть выбран соответствующий шрифт Unicode. Но в целом переход прошел довольно гладко.
4

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

3

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

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

  • 1
    Я думаю, что довольно часто объявлять API, который принимает указатели в качестве параметров указателей :) Также NativeUInt является относительно новым типом - когда-то Кардинал играл свою роль. Есть некоторые проблемы, подумайте о свойстве Tag (пока неизвестно, кем оно станет), типах wParam / lParam в сообщениях Windows, размеры записей могут измениться.
  • 2
    @Idsandon: Да, но для многих людей указатель - это просто причудливое имя кардинала, и это «заблуждение» работает довольно давно. Так что это возможная проблема. Таким образом, Tag может стать 64-битным? Я предполагаю, что это не сломает любой существующий код, хотя ...
Показать ещё 1 комментарий
3

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

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

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

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

  • 1
    TComponent.Tag должен быть NativeInt для обработки ожидаемого случая, когда люди раздают ссылки на TObject и тому подобное. Integer и Cardinal должны оставаться одинаковыми 32-разрядными, так как это общая политика для 64-разрядных Windows; это также должно уменьшить семантические изменения переключения битности цели. 64-битный встроенный ассемблер, вероятно, не будет существовать; надеюсь, поддержка связи будет существовать для NASM или аналогичного.
  • 0
    +1 главным образом за упоминание о совместимости с ASM, поскольку у меня были именно эти проблемы с момента выпуска Delphi XE2 (x64).
2

Помимо очевидных задач указателя ↔ 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.

  • 0
    Если не произойдет какой-либо неожиданной несовместимости, TComponent.Tag почти наверняка станет NativeInt.
  • 0
    FPC оставил это longint
Показать ещё 3 комментария
1

Мои 2 цента:

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

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

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

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

Нр

0

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

  • 0
    Что вы называете "словом"? В Delphi слово всегда является 16-битным значением. Так что, я думаю, вы говорили о «NativeInt» ... потому что DWord всегда будет оставаться 32-битным, например, целое число будет оставаться 32-битным ...
  • 0
    Я использую определение CE, а не определение Delphi.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню