Выделение больших блоков памяти с новыми - PullRequest
6 голосов
/ 26 февраля 2009

Мне нужно выделить большие блоки памяти новыми.

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

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

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

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

Ответы [ 5 ]

9 голосов
/ 26 февраля 2009

Относительно new в C ++ / GCC / Linux (32bit) ...

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

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

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

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

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

Вы пробовали это с обычным o'l malloc ?

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

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

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

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

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

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

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

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

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

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

-

Для чего бы то ни было, я выделил более 2-гигабайтных блоков данных с new в 32-битном Linux под g ++. Ваша проблема лежит в другом месте.

4 голосов
/ 26 февраля 2009

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

1 голос
/ 26 февраля 2009

Обновление:

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

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

0 голосов
/ 26 февраля 2009

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

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

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

0 голосов
/ 26 февраля 2009

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

...