LINUX.ORG.RU

C++. Предсказуемость поведения менеджера памяти.


0

1

Проверять результат выполнения new/malloc и т.п. - это конечно полезно, но не так прикольно. Не переключайте канал!

Софтина изредка в несколько потоков вызывает new(), прося что-то в районе 1...2 МБ памяти. Подобные запросы случаются одновременно из 4 потоков. Результат вызова не проверяется. Железных ядер - 4 (на всех нижеописанных платформах).

На тестовой платформе с linux 3.4.9 с 32 Гб ОЗУ работала безупречно.

На тестовой платформе с win-7 с 16 Гб ОЗУ иногда валилась. Валилась с одинаковой вероятностью и на виртуалке с 4 Гб ОЗУ.

Казалось бы - 16 гигов! Параллельно фотошопов не загружено. Если смотреть на стандартный «график использования ресурсов», то уровень занятости памяти валяется в нижних 20%.

Почему может так происходить, что при наличии кучи свободной памяти изредка происходят такие обломы? Ясно, что в таком топике на форуме невозможно объяснить и понять логику такой хитрой штуки, как менеджер памяти какой-либо ОС. Но хотя-бы какими его свойствами это может объясняться? Какие причины гипотетически тут могут быть? Он работает асинхронно от вызовов выделения памяти? Вызов на выделение памяти не блокирующий и может произойти в «неудобное время» (идёт процесс переупорядочения свободных блоков) и будет отклонён? Занятость диспетчера памяти своими служебными задачами рассматривается как отказ, равнозначный отсутствию свободной памяти? Почему вызывающий поток не будет заблокирован, чтобы дождаться окончания служебных процедур, если они кратковременные?

Ответ на: комментарий от kiverattes

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

Под Valgrind-ом гонял? Он хорошо отлавливает ошибки работы с памятью. Под Линуксом они могут оставаться незамеченными, а вот под Виндой стрелять.

Про утечку я наверное косвенно уже написал - при наличии свободных гигабайт происходит проблема выделения 1...2 Мб.

Я так понял, что ты писал про свободную физическую память. А я про виртуальную.

Relan ★★★★★
()
Ответ на: комментарий от Relan

Под valgrind-ом гонял много раз, ловил много разных ошибок, но думал что все самые плохие уже поймал. Попробую ещё погонять, но проблема в том, что приложение тяжёлое, много вычисляет и под valgrind такие тормоза, что добиться этой проблемы будет тяжело и очень долго. Но я попробую конечно.

Описанный bad_alloc у меня ловится под visual studio 2010 в дебажном режиме в виндовозе в описанном std::vector<>::resize(). В линуксе уронить приложение никак не получается, чтобы я ни делал...

kiverattes ★☆
() автор топика
Ответ на: комментарий от Relan

Утечка виртуальной памяти? А как это посмотреть в винде? Я думал, если диспетчер задач винды показывает, что приложение выделило 1.5 Гб и ещё 2.5 Гб свободно (окно с зелёными графиками), то типа ещё есть куда прыгать. Особенно при 16 физических гигах и 64 битах, когда после выделения 1.5 гигов свободно очень дофига.

Хм, правда я забыл написать, что само приложение собрано как 32 битное. Щас меня будут бить. Я не говорю про 4, но гига 2-то должно выделить хотя-бы... )

kiverattes ★☆
() автор топика
Последнее исправление: kiverattes (всего исправлений: 1)
Ответ на: комментарий от kiverattes

1) диспетчер задач - врёт, ставь process explorer
2) 32-х битное приложение в венде получает по-умолчанию 2 гб vram. Потому, если диспетчер задач тебе показывает 1.5 для 32-х битного приложения то там может уже и все два быть.

invy ★★★★★
()
Ответ на: комментарий от kiverattes

Хм, правда я забыл написать, что само приложение собрано как 32 битное. Щас меня будут бить. Я не говорю про 4, но гига 2-то должно выделить хотя-бы... )

Для 32 битной платформы совершенно не важно сколько на машине реальной памяти: 16 или 32 Гб. Все упирается в адресное пространство, которое ограниченно 4 Гб, причем 1 или 2 Гб (в зависимости от ОС) сразу откусывается ядром.

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

anonymous
()
Ответ на: комментарий от invy

Блин, забыл про process explorer. Раньше под винду больше кодил, его юзал... Про 2Гб vram интересно. Были подозрения.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

можно получить 4, если включить large address aware (кажется так).

а лучше конпилять под 64 бита... или искать что жрёт и оптимизировать :)

invy ★★★★★
()
Ответ на: комментарий от kiverattes

Утечка виртуальной памяти? А как это посмотреть в винде?

В обработчике исключения bad_alloc вызови GlobalMemoryStatusEx() и посмотри статистику. Делать это лучше поближе к месту генерации исключения, в идеале обернуть в try/catch тот самый std::vector<>::resize().

само приложение собрано как 32 битное

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

Если проблема таки в нехватке линейного пространства и это не утечка, то попробуй сказать линкеру /LARGEADDRESSAWARE. Тогда у приложения будет 4 ГБ адресного пространства на 64-битных виндах.

Relan ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.