Подтвердить что ты не робот

Преобразование 32-разрядного приложения в 64-битное приложение в C

В настоящее время я работаю над преобразованием приложения 32 бит в приложение с 64 битами в C. Это приложение в настоящее время работает над архитектурой x86 (Windows, osx, Unix, Linux). Поэтому, прежде чем начинать кодирование, я хотел бы знать, что мне нужно учитывать при преобразовании приложения.

4b9b3361

Ответ 1

  • Узнайте, кто это написал. Это идиот? Это они из нескольких лет назад? Вы можете задать им вопросы? Знают ли они о существовании множества платформ и систем? Знание умом автора (ов) программы поможет вам понять проблемы, когда вы столкнетесь с ними.
  • Загрузите и запустите 64-разрядную среду сборки/сборки.
  • Заменить long с помощью int. Осознайте, что LONG не LONG.
  • Замените (int)&x отбрасывание и ввод текста с помощью intptr_t и (unsigned int)&x с помощью uintptr_t
  • Проверяйте все, что опирается на кастинг-структуры на char*, чтобы сделать с ним арифметику указателей.
  • Regex ищет \< 4 \ > в случае, если вы предположили 4 = sizeof(void*)
  • Будьте терпеливы. Когда вы обнаружите проблему, посмотрите в другом месте, если та же проблема существует, и заверните решение в макрос.
  • Старайтесь не использовать #ifdef RUN64 или что-то подобное. Вы пожалеете об этом, если 128-битные платформы будут входить в моду.
  • Инкапсулируйте все свои изменения с точки зрения некоторых централизованных макросов, которые скрывают различия переносимости в других местах вашей программы.
  • Используйте тестер покрытия, чтобы убедиться, что вы все покрыли (при необходимости)

EDIT добавлен uintptr_t, как указано в комментарии.

Ответ 2

Одна потенциальная проблема, о которой уже не упоминалось, заключается в том, что если ваше приложение читает или записывает двоичные данные с диска (например, читайте массив структур с использованием fread), вам нужно будет очень тщательно проверить и, возможно, завершить работу с двумя читателей: один для устаревших файлов и один для 64-битных файлов. Или, если вы стараетесь использовать такие типы, как uint32_t и т.д. Из заголовочного файла <stdint.h>, вы можете переопределить свои структуры для совместимости бит-бит. В любом случае, двоичный ввод/вывод - это вещь, над которой нужно следить.

Ответ 3

Это действительно зависит от приложения и того, как оно было закодировано. Некоторый код можно просто перекомпилировать с помощью 64-битного компилятора, и он будет работать, но обычно это происходит только в том случае, если код был разработан с учетом переносимости.

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

Довольно много предупреждений о броске и компиляторе - это красный флаг, который необходимо проверить. Если код не был "предупреждающим чистым", чтобы начать с этого, это также признак того, что может потребоваться много работы.

Ответ 4

Если вы использовали правильные типы для своих значений - например. size_t, ptrdiff_t, uintptr_t, типы фиксированного размера от stdint.h, где это необходимо, и не имеют размер жесткого кода, ваш код должен работать из коробки.

Ответ 5

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

Почему это проблема? Ну, это не так, если ваш код не предполагает, что sizeof (int) == sizeof (void *). Это может привести к неприятным ошибкам указателя.

Ответ 6

Ну, в принципе, количество изменений довольно невелико, но это все равно будет важной задачей, если приложение не будет тщательно написано, чтобы начать с него несколько портативно.

Основное отличие состоит в том, что указатели имеют ширину 64 бит, но большинство других типов данных не изменяется. Инт все еще 32 бит, а длинный, вероятно, еще 32 бит. Поэтому, если ваш код переместится между ints и указателями, это сломается. Точно так же любая структура или подобное, которое зависит от конкретного смещения члена, может нарушиться, потому что другие члены теперь могут быть больше и поэтому меняют смещение.

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

Ответ 7

Двумя основными отличиями между 32-битным и 64-битным программированием в C являются sizeof (void *) и sizeof (long). Основная проблема, с которой вы столкнетесь, заключается в том, что большинство систем Unix используют стандарт I32LP64, который определяет длину 64 бит, а Win64 использует стандарт IL32LLP64, который определяет длину 32 бита. Если вам необходимо поддерживать кросс-платформенную компиляцию, вы можете использовать набор основанных на архитектуре typedefs для 32-битных и 64-разрядных целых чисел, чтобы гарантировать, что весь код будет вести себя последовательно. Это предусмотрено как часть стандарта stdint.h как часть стандарта C99. Если вы не используете компилятор C99, вам может потребоваться свернуть собственный эквивалент

Как уже отмечалось в других разделах, первичными проблемами для преобразования являются код, предполагающий sizeof (int) == sizeof (long) == sizeof (void *), код для поддержки данных, которые были записаны на диск и код для кросс-платформенной IPC.

Для хорошего обзора истории за этим взгляните на эту статью из очереди ACM.

Ответ 8

Уже есть много хороших ответов.

Рассмотрим использование Gimpel Lint. Он может точно указать типы проблем, которые являются проблематичными. Если ваш опыт похож на мой, он также покажет вам массу ошибок в системе, не связанной с 32-битным портом.