2009-07-22 1 views
4

Работа с портированием 32-битного приложения на Windows C++ на 64-разрядное. К сожалению, код использует частое кастинг в обоих направлениях между значениями DWORD и указателя.Как зарезервировать нижнюю 4GB виртуальную машину в приложении x64 C++

Одна из идей состоит в том, чтобы как можно раньше зарезервировать первые 4 ГБ виртуального пространства процесса во время запуска процесса, чтобы все последующие вызовы в резервную память были с виртуальных адресов более 4 ГБ. Это приведет к ошибке нарушения прав доступа к любому небезопасному методу от указателя к DWORD, а затем обратно к указателю и поможет ловить ошибки раньше.

Когда я смотрю карту памяти очень простой одной линии на C++-программе, есть много библиотек, загруженных в нижнем 4 ГБ? Есть ли способ убедиться, что все библиотеки и т. Д. Загружаются только выше 4 ГБ?

Благодаря

ответ

1

Лучшим решения, чтобы исправить эти слепки ...

Вы можете уйти с ним усеченным указателем независимо (то же, приведение к POINTER_32), потому что я считаю, окно предпочитает нижний 4Гб для вашего приложения. Это никоим образом не гарантировано. Вам лучше всего решить эту проблему.

Ищите код для "(DWORD)" и исправьте все, что найдете. Нет лучшего решения ...

Что вы просите, это, по сути, запустить 64-разрядный код в 32-разрядном режиме памяти с включенным AWE (т.е. потерять все реальные преимущества 64-разрядного). Я не думаю, что Microsoft могла бы беспокоиться, предоставляя это для столь маленького выигрыша ... и кто может обвинить их?

+1

Вы прочитали вопрос? Плакат не спрашивает, как избежать адресов более 4 ГБ. (И если да, то ответ будет состоять в том, чтобы передать/LARGEADDRESSAWARE = ​​NO в компоновщик.) И есть намного лучшие способы найти проблемы усечения указателя, чем grep-код для приведения в стиле C. – bk1e

6

Скомпилируйте свой проект с помощью переключателя /Wp64 (обнаружение 64-разрядных проблем с переносимостью) и исправьте все предупреждения.

+0

Разве этот вариант не объявлен как «устаревший»? – LiraNuna

+0

Спасибо. Я попробую этот флаг. – CeeMan

+0

Просто компиляция с компилятором x64 должна содержать все предупреждения (и более точно, чем/Wp64 - вот почему этот переключатель устарел). –

2

Вы можете вставлять вызовы на VirtualAlloc() как можно раньше в приложение, чтобы выделить память в нижнем 4 ГБ. Если вы используете параметр MEM_RESERVE, тогда выделяется только пространство виртуальной памяти, и поэтому это будет использовать только очень небольшое количество реальной ОЗУ.

Однако это поможет вам только для памяти, выделенной из кучи - любые статические данные в вашей программе будут уже выделены до WinMain(), и поэтому вы не сможете изменить его местоположение.

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

+0

Спасибо. Я планирую использовать VirtualAlloc в одном из DllMain, если это возможно. Проблема в MSVC Runtime загружается до 4 ГБ. Исполняемый файл имеет предпочтительный адрес, превышающий 4 ГБ, поэтому его можно загружать выше 4 ГБ. – CeeMan

+0

Вы можете изменить местоположение статических/глобальных данных и кода вашей программы (или DLL), установив свой предпочтительный базовый адрес во время ссылки или с помощью файла rebase.exe, чтобы изменить его предпочтительный базовый адрес. – bk1e

+0

Некоторая некорректная загрузка DLL с задержкой загрузки может позволить вам вызвать VirtualAlloc() перед загрузкой большинства DLL. Очевидно, что вам все равно потребуется Kernel32.DLL. – MSalters

2

Брюс Доусон опубликовал код для метода, чтобы зарезервировать нижний 4 Гб VM:

https://randomascii.wordpress.com/2012/02/14/64-bit-made-easy/

Он резервирует большую часть адресного пространства (не фактическую память) с использованием VirtualAlloc, затем идет после кучи процесса с HeapAlloc и заканчивает кучу CRT с помощью malloc. Это просто, быстро и отлично работает. На моей машине он составляет около 3,8 ГБ виртуальных распределений и только 1 МБ фактических распределений.

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

+1

Ранняя технология VirtualAlloc не будет препятствовать тому, чтобы весь код находился в нижней части 4 ГБ, но для указателей функций реже усекается, поэтому это может иметь значение. Кроме того, ASLR должна размещать ваши двоичные файлы выше строки 4 ГБ, особенно если вы поместили ее в режим с дополнительной энтропией. –

Смежные вопросы