Как программист, что мне нужно беспокоиться при переходе на 64-битные окна?
Большая часть моего недавнего программирования была в 32-битной Windows с использованием C/С++/С#/VB6. В последнее время мои клиенты спрашивают, будет ли мой код работать в 64-битной Windows.
Мне интересно, какие устаревшие функции я могу использовать, которые будут разбиваться на 64-битную Windows? Каковы некоторые реальные проблемы, о которых мне нужно думать и беспокоиться?
Очевидно, что я буду тестировать свой код на 64-битной ОС, но я хотел бы знать, какие общие проблемы нужно искать. Я больше беспокоюсь о существующих двоичных файлах, но я открыт для комментариев о том, о чем беспокоиться при перекомпиляции (где это возможно).
EDIT: хороший список 64-битных ошибок портирования.
Ответы
Ответ 1
Статьи:
20 вопросов портирования кода С++ на 64-битной платформе
Забытые проблемы разработки 64-битных программ
64 бит, Wp64, Visual Studio 2008, Viva64 и все остальное...
Обнаружение ловушек во время миграции кода C и С++ в 64-разрядную Windows
архитектура AMD64 (EM64T)
и
Инструмент Viva64 - для проверки 64-разрядных программ:
Viva64: что это такое и для кого оно предназначено?
Ответ 2
Насколько мне известно, самая важная вещь о переносе кода C/С++ в 64-разрядную Windows - это проверить ваше приложение с включенными MEM_TOP_DOWN
распределениями (AllocationPreference
значение реестра), как описано в 4-гигабайтная настройка:
Чтобы принудительно распределять ассигнования из более высоких адресов перед более низкими адресами для целей тестирования, укажите MEM_TOP_DOWN
при вызове VirtualAlloc
или установите следующее значение реестра в 0x100000:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference
Когда это имеет значение?
- Если у вас есть существующие 32-разрядные EXE файлы, которые были построены с помощью
/LARGEADDRESSAWARE
опции компоновщика MSVC (или которые имеют флаг IMAGE_FILE_LARGE_ADDRESS_AWARE
устанавливаются в их PE-заголовках с помощью других средств, таких как editbin.exe
), затем они получают полное 4 ГБ виртуального адресного пространства в 64-битной Windows, и вы должны протестировать их с установленным значением реестра AllocationPreference
.
- Если у вас есть 32-разрядные DLL файлы, которые могут быть загружены EXE с большими адресами, вы должны протестировать их с установленным значением реестра
AllocationPreference
.
- Если вы перекомпилируете свой код C/С++ в 64-разрядный EXE или DLL, вы должны протестировать его с установленным значением реестра
AllocationPreference
.
Если ваше приложение C/С++ попадает в одну из этих трех категорий и вы не тестируете с помощью распределений MEM_TOP_DOWN
, тестирование вряд ли поймает любые ошибки усечения/подписи указателя в вашем коде.
Вторая важная вещь, если вы используете MSVC и перекомпилируете код C/С++ для 64-разрядной версии, - это использовать параметр компилятора /Wp64
для вашей 64-битной сборки:
- Это заставит компилятор выдавать предупреждения для типов, которые усекают указатели или расширяют более мелкие интегральные типы в указатели (даже если используется
reinterpret_cast
или приведение в стиле C), а также некоторые другие проблемы с 64-разрядным переносом.
- Да, документация говорит, что вместо компиляции с
/Wp64
вы должны использовать компилятор, ориентированный на 64-битную платформу, но один не будет улавливать усечение/расширение указателя во время компиляции. Использование компилятора, который нацелен на 64-разрядный и, включающий параметр компилятора /Wp64
для 64-битной сборки, будет захватывать многие проблемы усечения/расширения указателя во время компиляции, и это сэкономит ваше время в длинных работать.
- К сожалению, с MSVC 2008 это также приведет к "предупреждению командной строки" для каждой единицы перевода, в которой говорится, что параметр
/Wp64
устарел. Я могу понять, почему опция устарела для 32-битных сборников (где это злой хак, который требует аннотации многих ваших typedef), но он досадно, что он также устарел для 64-битных сборников (где это действительно полезно).
Ответ 3
Возможно, было бы легче перенести .NET-код, если у вас есть 100% -ный "безопасный управляемый код типа".
Вы можете просто скопировать его на 64-битную платформу и успешно запустить ее под 64-разрядной CLR.
Проверьте ссылку MSDN на перенос 32-разрядного управляемого кода на 64-разрядный.
Btw, hanselman в блоге о теме недавно.
Ответ 4
Если вы говорите о 32-битных программах, вам нечего беспокоиться, так как Windows 64 будет запускать их под эмуляцию как 32-разрядные. Любые проблемы с будущими версиями Windows (например, Windows 7) скорее всего будут несовместимыми, чем проблемами с 64-разрядной ОС.
Однако, если ваш управляемый код скомпилирован для целевой платформы "Любой процессор" и вы делаете вызовы в неуправляемый код (например, PInvoke) или зависят от других сборок, тогда есть некоторые вещи, о которых нужно знать. Скотт Гензельман post о CLR x86/x64 охватывает это и является хорошим объяснением CLR на Win32/64.
При разработке 64-битных исходных программ Руководство по программированию для 64-разрядной Windows является хорошим руководством. В основном это сводится к указателям и размерам типов данных:)
Ответ 5
32-разрядные программы будут отлично работать на 64-битных окнах. До тех пор, как вы, конечно, не делаете никаких драйверов устройств.
Если вы впервые скомпилируете свое программное обеспечение в виде 64-битного программного обеспечения, вам необходимо позаботиться о следующем:
- указатель имеет ширину 64 бит, а int - 32 бит. Не храните указатели в ints, ваш код сломается.
- Для 64-битного процесса нужны 64-разрядные библиотеки DLL. Если вы зависите от DLL третьей части, убедитесь, что они также предоставляются в 64 бит. Если вам необходимо установить связь между 32-битным процессом и 64-разрядным процессом, вам понадобятся некоторые из многих способов IPC в Windows. Вызов функций напрямую невозможен.
- Системные каталоги на 64-битных Windows отличаются от 32-разрядных версий Windows. Если у вас есть жесткие кодированные пути, вам может потребоваться проверить их снова.
Ответ 6
Если вы используете DLL-инъекцию по какой-либо причине, у вас возникнут проблемы.
Ответ 7
С точки зрения C/С++....
Очевидным является то, что размер int станет 8 байтами вместо 4 байтов. Если какой-либо из ваших кодов зависит от этого, вы можете получить неожиданные результаты. Структура и выравнивание переменных могут меняться. Вы можете преодолеть это с помощью пакета #pragma, но я не очень хорошо разбираюсь в настройках и упаковке.
Если вы используете какие-либо объединения с ints в них, поведение может измениться.
Если вы используете какие-либо структуры битовых полей, на основе ints дополнительные 32 бита могут вызвать путаницу. Значок бит не будет таким, как вы думали.
Если вы кодируете любые шестнадцатеричные константы и ожидаете, что знаки будут отрицательными, могут возникнуть проблемы. пример
0x8000000 - отрицательное число в виде журнала или 32-битное целое число. 0x80000000 как целое число на 64-битной платформе - это положительное число. для прямого набора знакового бита вам нужно будет использовать 0x80000000 00000000 (только встроенное пространство для чтения)
Также я ожидаю, что размер__t будет расти соответствующим образом. Если вы делаете какие-либо выделения на основе MAX_INT, они будут намного больше.
Чтобы избежать аномалий такого типа, я обычно придерживаюсь longs вместо ints.
Ответ 8
Является ли 32-разрядная эмуляция действительно доказательством пули? Я видел, что реестр выложен немного по-другому. Мне просто интересно, какие типичные вещи не работают...
Кроме того, каталог C:\windows\SYSTEM32 может содержать только 64-разрядные библиотеки DLL. Если у вас 32-разрядная DLL, вам нужно поместить ее в папку C:\windows\syswow64\