Выделение больших блоков памяти новыми

У меня есть необходимость выделить большие блоки памяти с помощью new.

Я застрял с использованием new, потому что я пишу макет для производителя приложения из двух частей. Фактический код производителя выделяет эти большие блоки, и мой код несет ответственность за их удаление (после их обработки).

Есть ли способ убедиться, что мое приложение способно выделять такой большой объем памяти из кучи? Могу ли я увеличить размер кучи?

В моем случае это 64 блока по 288000 байт. Иногда мне нужно выделить 12, а иногда мне нужно выделить 27. Я получаю исключение std::bad_alloc.

Это: C++, GCC для Linux (32 бита).


person JeffV    schedule 26.02.2009    source источник
comment
Вам нужно все это за один раз? В противном случае вы можете использовать пул памяти и настраиваемый распределитель для управления пулом.   -  person dirkgently    schedule 26.02.2009
comment
Как я уже сказал, я пытаюсь издеваться над тем, что будет делать производящий код. Я бы использовал статически выделенный пул памяти, если бы мог.   -  person JeffV    schedule 26.02.2009
comment
Вы можете использовать статически выделенный пул и заменить свои вызовы для удаления функцией «FreeBlock». Таким образом, вы можете проверить, заполнили ли вы каждый полученный блок.   -  person Andrew Khosravian    schedule 26.02.2009
comment
Да, я мог бы это сделать, но мне все равно хотелось бы знать, почему я не могу выделить доступную память.   -  person JeffV    schedule 26.02.2009


Ответы (5)


arrow_upward
9
arrow_downward

Что касается нового в C++/GCC/Linux(32bit)...

Это было давно, и это зависит от реализации, но я верю, что new будет за кулисами вызывать malloc(). Malloc(), если вы не запросите что-то, превышающее адресное пространство процесса или за пределами указанных (ulimit/getrusage) ограничений, не завершится ошибкой. Даже если в вашей системе недостаточно RAM+SWAP. Например: malloc(1gig) в системе с 256 Мб ОЗУ + 0 SWAP, как мне кажется, будет успешным.

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

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

Так что тот факт, что вы видите исключения std::bad_alloc, "интересен".

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

Вы пробовали это с простым malloc?

Вы пробовали запустить программу "бесплатно"? Достаточно ли у вас памяти?

Как уже предлагали другие, проверили ли вы limit/ulimit/getrusage() на жесткие и мягкие ограничения?

Как именно выглядит ваш код? Я предполагаю, что новый ClassFoo [ N ]. Или, возможно, новый символ [ N ].

Что такое sizeof(ClassFoo)? Что такое Н?

Выделение 64 * 288000 (17,58 МБ) должно быть тривиальным для большинства современных машин ... Вы работаете на встроенной системе или на чем-то другом?

В качестве альтернативы вы связываетесь с настраиваемым распределителем new? Есть ли в вашем классе собственный распределитель new?

Выделяет ли ваша структура данных (класс) другие объекты как часть своего конструктора?

Кто-то вмешивался в ваши библиотеки? У вас установлено несколько компиляторов? Вы используете неправильные пути включения или библиотеки?

Вы связываетесь с устаревшими объектными файлами? Вам просто нужно перекомпилировать все ваши исходные файлы?

Можете ли вы создать тривиальную тестовую программу? Всего пара строчек кода, воспроизводящих ошибку? Или ваша проблема в другом месте, а проявляется только здесь?

--

Что бы это ни стоило, я выделил более 2 ГБ блоков данных с помощью new в 32-битном Linux под g++. Ваша проблема в другом.

person Mr.Ree    schedule 26.02.2009

arrow_upward
4
arrow_downward

Возможно, вы ограничены ulimit процесса; запустите ulimit -a и проверьте ограничения на виртуальную память и размер сегмента данных. Кроме этого, можете ли вы опубликовать свой код распределения, чтобы мы могли увидеть, что на самом деле происходит?

person Kieron    schedule 26.02.2009
comment
Я проверил с помощью getrlimit (RLIMIT_AS, &lim), он сообщает о 4 ГБ на текущем и максимальном. - person JeffV; 26.02.2009
comment
@Jeff: Вы пытаетесь выделить всего около 18 МБ! Это гроши на любом современном компьютере. Внутри вашей программы должно быть что-то еще, выделяющее тонны памяти. - person j_random_hacker; 26.02.2009

arrow_upward
1
arrow_downward

Обновлять:

С тех пор я исправил ошибку индексации массива, и теперь он правильно распределяется.

Если бы мне пришлось угадывать... Я ходил по всей своей куче и возился со структурами данных malloc. (??)

person JeffV    schedule 26.02.2009
comment
Это, безусловно, сделать это! Иногда я использую ВСТРОЕННЫЕ методы доступа с инструкциями assert, чтобы выявить такие проблемы на этапе отладки. (Они компилируются для производственного кода.) - person Mr.Ree; 27.02.2009

arrow_upward
0
arrow_downward

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

person Community    schedule 26.02.2009

arrow_upward
0
arrow_downward

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

Если этот «кто-то еще» есть в вашей программе, вы сможете найти его с помощью Valgrind.

Если этот кто-то еще является другой программой, вы сможете определить это, перейдя к другому уровень выполнения (хотя вы не обязательно будете знать виновника).

person Max Lybbert    schedule 26.02.2009