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

StackOverflow https://stackoverflow.com/questions/2288728

Вопрос

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

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

Это было полезно?

Решение

слепо применяя 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

(это шестнадцатеричный код 0x100000.требует перезагрузки Windows, конечно)

если этот переключатель включен, вы сможете выявить проблемы «раньше», а не «позже».в идеале вы увидите их «с самого начала».

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

выводы:

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

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

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


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

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


ПС:
Также очень «связанным» и весьма интересным является переход с 32-битного кода на 64-битный.
примеры см.:

Другие советы

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

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

Это не так уж и сложно, как вы заметили.

Рэймонд Чен - в своем блоге Старая новая вещь - освещает проблемы с включением для всех (32-битных) приложений.

Нет, «устаревший код» в этом контексте (C/C++) — это не только код, который играет ужасные трюки со старшим разрядом указателей.

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top