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

У меня есть необходимость выделить большие блоки памяти с помощью 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)


Что касается нового в 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

Возможно, вы ограничены 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

Обновлять:

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

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

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

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

person Community    schedule 26.02.2009

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

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

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

person Max Lybbert    schedule 26.02.2009