Выделить более 1 ГБ памяти на 32-битной XP

Я столкнулся с нечетной проблемой, мой процесс не может выделить больше, чем кажется чуть ниже 1 гигабайта. Диспетчер задач Windows "Mem Usage" показывает значения, близкие к 1 GiB, когда мое программное обеспечение предоставляет исключение bad_alloc. Да, я проверял, что значение, переданное в распределение памяти, разумно. (не существует никаких условий гонки/коррупции, которые сделают это неудачным). Да, мне нужна вся эта память, и вокруг нее нет никакого способа. (Это буфер для изображений, который не может быть сжат дальше)

Я не пытаюсь выделить целую 1 гигабайтную память за один раз, там есть несколько распределений по 300 Мбайт каждый. Это вызовет проблемы? (Я попытаюсь посмотреть, улучшится ли создание более мелких распределений). Есть ли какой-нибудь компилятор или что-то еще, что я должен установить, чтобы пройти 1 гигабайт? Я видел, как другие жаловались на лимит 2 гигабайт, что было бы хорошо для меня.. Мне просто нужно немного больше:). Я использую VS 2005 с пакетом обновления 1 (SP1), и я запускаю его на 32-разрядной версии XP и на С++.

Ответ 1

В 32-разрядной ОС процесс имеет общее адресное пространство 4 ГБ.

В Windows половина этого параметра отключена, поэтому ваш процесс имеет 2 ГБ.

Это 2 ГБ непрерывной памяти. Но он фрагментирован. Ваш исполняемый файл загружается по одному адресу, каждая DLL загружается по другому адресу, затем - стек, а также распределение кучи и так далее. Поэтому, хотя ваш процесс, вероятно, имеет достаточно свободного адресного пространства, нет смежных блоков, достаточно больших для выполнения ваших запросов на память. Таким образом, создание небольших распределений, вероятно, решит его.

Если ваше приложение скомпилировано с флагом LARGEADDRESSAWARE, ему будет разрешено использовать столько же оставшихся 2 ГБ, сколько Windows может сэкономить. (И ценность этого зависит от вашей платформы и среды.

  • для 32-разрядного кода, работающего на 64-разрядной ОС, вы получите полное адресное пространство 4 ГБ
  • для 32-разрядного кода, запущенного на 32-разрядной ОС без загрузочного переключателя /3GB, флаг ничего не означает
  • для 32-разрядного кода, запущенного в 32-разрядной ОС с загрузочным коммутатором /3GB, вы получите 3 ГБ адресного пространства.

Таким образом, установка флага всегда является хорошей идеей, если ваше приложение может обрабатывать его (это в основном флаг функции. Он сообщает Windows, что мы можем обрабатывать больше памяти, поэтому, если Windows тоже может, она должна просто идти вперед и давать нам как можно больше адресного пространства), но вы, вероятно, не можете полагаться на это, имея эффект. Если вы не находитесь на 64-битной ОС, вряд ли вы много покупаете. (Необходим загрузочный переключатель /3GB, и он, как известно, вызывает проблемы с драйверами, особенно видеодрайверами).

Ответ 2

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

Вы должны переделать структуры памяти.

Ответ 3

Вы правы, чтобы подозревать более крупные 300 МБ распределения. Ваш процесс сможет приблизиться к 2 ГБ (3, если вы используете ключ загрузки /3GB boot.ini и флаг ссылки LARGEADDRESSAWARE), но не как большой смежный блок.

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

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

Ответ 4

Вы также можете проверить эту функцию из MSDN. 1GB звонит отсюда:

Этот параметр должен быть больше или равен 13 страницам (например, 53 248 на системах с размером страницы 4 КБ) и меньше, чем в масштабе всей системы максимум (количество доступных страниц минус 512 страниц). Размер по умолчанию составляет 345 страниц (например, это 1,413,120 байт на системах с 4K).

Здесь они упомянули, что максимальное количество страниц, разрешенных для процесса, составляет 345 страниц, что немного больше 1 ГБ.

Ответ 5

Когда у меня есть несколько больших распределений, как это сделать, я использую функцию Windows VirtualAlloc, чтобы не нажимать на распределитель по умолчанию.

Другой путь вперед может заключаться в использовании nedmalloc в вашем проекте.