Проблема нехватки памяти (?) В Win32 (по сравнению с Linux) - PullRequest
0 голосов
/ 24 октября 2009

У меня следующая проблема:

Программа, запускаемая на машине с Windows (32-битная память, 3,1 ГБ, VC ++ 2008 и скомпилированный код mingw), завершается с ошибкой bad_alloc (после выделения около 1,2 ГБ; исключение выдается при попытке выделить вектор с 9 миллионами удваивается, т.е. около 75 МБ) с достаточным объемом оперативной памяти (по крайней мере, в соответствии с диспетчером задач).

Та же программа, запущенная на машинах Linux (32-битная, 4 ГБ памяти; 32-битная, 2 ГБ памяти), работает нормально с пиковым использованием памяти около 1,6 ГБ. Интересно, что код win32, сгенерированный mingw, запущенным на машине Linux 4Gb под Wine, также не работает с bad_alloc, хотя и в другом (более позднем) месте, чем при запуске под windows ...

Каковы возможные проблемы?

  • фрагментация кучи? (Как я узнаю? Как это можно решить?)
  • куча коррупции? (Я запустил код с включенным pageheap.exe без сообщений об ошибках; реализовал векторный доступ с проверкой границ - опять же, без ошибок; код по существу не содержит указателей, используются только std::vector s и std::list s. Бег программа под Valgrind (memcheck) занимает слишком много памяти и преждевременно завершает работу, но не находит ошибок)
  • Недостаточно памяти ??? (Должно быть достаточно памяти)

Кроме того, что может быть причиной сбоя версии Windows, пока версия linux работает (и даже на машинах с меньшим объемом памяти)? (Также обратите внимание, что флаг компоновщика / LARGEADDRESSAWARE используется с VC + 2008, если это может иметь какой-либо эффект)

Любые идеи будут высоко оценены, я в конце концов с этим ...: - (

Ответы [ 4 ]

5 голосов
/ 24 октября 2009

Это не имеет никакого отношения к тому, сколько оперативной памяти находится в вашей системе. У вас заканчивается виртуальное адресное пространство. Для 32-разрядного процесса ОС Windows вы получаете виртуальное адресное пространство 4 ГБ (независимо от того, сколько оперативной памяти вы используете) из 2 ГБ для режима пользователя (3 ГБ в случае LARGEADDRESSAWARE) и 2 ГБ для ядра. Когда вы попытаетесь выделить память, используя new, ОС попытается найти блок виртуальной памяти contiguos, который достаточно велик, чтобы удовлетворить запрос на выделение памяти. Если ваше виртуальное адресное пространство сильно фрагментировано или вы запрашиваете огромный блок памяти, то оно не сможет вызвать исключение bad_alloc. Проверьте, сколько виртуальной памяти использует ваш процесс.

2 голосов
/ 24 октября 2009

С Windows XP x86 и настройками по умолчанию 1,2 ГБ - это почти все адресное пространство, которое вы оставили для своей кучи после того, как системные библиотеки, ваш код, стек и другие вещи получили свою долю. Обратите внимание, что для большой адресной программы требуется загрузка с флагом загрузки / 3GB, чтобы попытаться увеличить объем процесса до 3 ГБ. Флаг / 3GB вызывает нестабильность во многих системах XP, поэтому по умолчанию он не включен.

Варианты сервера Windows x86 дают вам больше адресного пространства, как с помощью разделения на 3 ГБ / 1 ГБ, так и с помощью PAE, чтобы разрешить использование всех ваших 4 ГБ ОЗУ.

В Linux x86 по умолчанию используется разделение 3 ГБ / 1 ГБ.

64-битная ОС даст вам больше адресного пространства даже для 32-битного процесса.

0 голосов
/ 25 октября 2009

Чтобы подробнее узнать о виртуальной памяти: Ваше приложение терпит неудачу, когда оно пытается выделить один массив размером 90 МБ, и не существует непрерывного пространства виртуальной памяти, где оно может поместиться слева. Возможно, вам удастся продвинуться немного дальше, если вы переключитесь на структуры данных, которые используют меньше памяти - возможно, некоторый класс, который приближается к огромному массиву, используя дерево, где все данные хранятся в 1 МБ (или около того) конечных узлах. Кроме того, при использовании c ++ при выполнении огромного количества выделений действительно помогает, если все эти большие выделения имеют одинаковый размер, это помогает повторно использовать память и значительно снижает фрагментацию.

Однако в долгосрочной перспективе правильным решением будет просто перейти на 64-битную систему.

0 голосов
/ 24 октября 2009

Вы компилируете в режиме Debug? Если это так, то при выделении будет генерироваться огромное количество данных отладки, которые могут вызвать ошибку, с которой вы столкнулись, с подлинной нехваткой памяти. Попробуйте в Release проверить, решает ли это проблему.

Я испытал это только с VC, а не с MinGW, но тогда я тоже не проверял, это все еще может объяснить проблему.

...