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

Недостатки использования /LARGEADDRESSAWARE для 32-битных исполняемых файлов Windows?

Нам нужно связать один из наших исполняемых файлов с этим флагом, поскольку он использует много памяти.
Но зачем присылать один файл EXE файла. Почему бы не стандартизировать on/LARGEADESSESSAWARE?

Итак, вопрос: есть ли что-то неправильное в использовании /LARGEADDRESSAWARE, даже если оно вам не нужно. Почему бы не использовать его как стандарт для всех EXE файлов?

4b9b3361

Ответ 1

слепое применение флага LargeAddressAware к вашему 32-битовому исполняемому файлу развертывает тиковую бомбу замедленного действия!

установив этот флаг, который вы подтверждаете ОС:

да, мое приложение (и все DLL, загружаемые во время выполнения) может справиться с адресами памяти до 4 ГБ.
поэтому не ограничивайте VAS для процесса до 2 ГБ, а разблокируйте весь диапазон (4 ГБ) ".

но можете ли вы действительно гарантировать? вы берете на себя ответственность за все системные DLL, распространяемые компоненты microsoft и сторонние модули, которые может использовать ваш процесс?

обычно, распределение памяти возвращает виртуальные адреса в низком-высоком порядке. поэтому, если ваш процесс не потребляет много памяти (или имеет очень фрагментированное виртуальное адресное пространство), он никогда не будет использовать адреса за пределами границы 2 ГБ. это скрывает ошибки, связанные с высокими адресами.

если такие ошибки существуют, их трудно идентифицировать. они будут спорадически появляться "рано или поздно". это просто вопрос времени.

К счастью, в ОС Windows есть чрезвычайно удобный общесистемный коммутатор:
для целей тестирования используйте параметр реестра MEM_TOP_DOWN.
это заставляет все распределения памяти идти сверху вниз, вместо нормального снизу вверх.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"AllocationPreference"=dword:00100000

(это hex 0x100000. требуется перезагрузка Windows, конечно)

с включенным коммутатором вы будете идентифицировать проблемы "скорее", а не "позже". в идеале вы увидите их "с самого начала".

Примечание: для первого анализа я настоятельно рекомендую инструмент VMmap (SysInternals).

выводы:

при применении флага LAA к вашему 32-битовому исполняемому файлу необходимо полностью протестировать его на ОС x64 с помощью набора TopDown AllocationPreference.

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

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


примечание к тестированию:

переключатель реестра MemTopDown не достигает желаемых результатов для модульных тестов, которые выполняются "тестовым runner", который сам не поддерживает LAA.
см. Тестирование устройств для совместимости с x86 LargeAddressAware


PS:
также очень "родственный" и довольно интересный переход от 32-битного кода к 64-битной.
для примеров см.

Ответ 2

Потому что много устаревшего кода написано с ожиданием, что "отрицательные" указатели недействительны. Все, что находится в верхних двух Gb 32-битного процесса, имеет набор msb.

Таким образом, Microsoft гораздо безопаснее играть в нее и требует приложений, которые (а) нуждаются в полной 4Gb и (б), были разработаны и протестированы в сценарии большой памяти, чтобы просто установить флаг.

Его нет - как вы заметили - это трудно.

Раймонд Чен - в своем блоге The Old New Thing - охватывает проблемы с включением всех (32-битных) приложений.

Ответ 3

Нет, "устаревший код" в этом контексте (C/С++) не является исключительно кодом, который воспроизводит уродливые трюки с MSB указателей.

Он также включает весь код, который использует "int" для хранения разницы между двумя указателями или длиной области памяти вместо того, чтобы использовать правильный тип "size_t": подписанный "int" имеет 31 бит и не может обрабатывать значение более 2 Гб.

Способ вылечить значительную часть вашего кода состоит в том, чтобы пройти его и исправить все эти безобидные предупреждения "смешение подписанных и неподписанных". Он должен выполнять значительную часть задания, по крайней мере, если вы не определили функцию, где аргумент типа int на самом деле является длиной памяти.

Однако этот "устаревший код", вероятно, будет работать довольно долго, даже если вы ничего не исправите.

Вы будете ломаться только тогда, когда вы выделите более 2 Гб в одном блоке. Или когда вы сравните два несвязанных указателя, которые находятся на расстоянии более 2 Гб друг от друга.
Поскольку сравнение несвязанных указателей технически - это поведение undefined, вы не столкнетесь с таким количеством кода, который это делает (но вы никогда не можете быть уверены).
И очень часто, даже если вам нужно больше, чем 2Gb, ваша программа на самом деле никогда не выделяет одиночные распределения, которые больше. Фактически в Windows, даже с LARGEADDRESSAWARE, вы по умолчанию не сможете выделить так много, как организована память. Вам нужно будет перетасовать системную DLL, чтобы получить непрерывный блок размером более 2 ГБ

Но законы Мерфи говорят, что однажды код сломается, просто так, что это произойдет очень долго после того, как вы включите LARGEADDRESSAWARE без проверки, и когда никто не запомнит, что это было сделано.