2010-09-08 7 views
3

Можно ли в C++ для создания пользовательского аллокатора, который работает просто как это:Создание настраиваемого пула памяти/распределителя памяти?

{ 
    // Limit memory to 1024 KB 
    ScopedMemoryPool memoryPool(1024 * 1024); 

    // From here on all heap allocations ('new', 'malloc', ...) take memory from the pool. 
    // If the pool is depleted these calls result in an exception being thrown. 

    // Examples: 
    std::vector<int> integers(10); 
    int a * = new int [10]; 
} 

Я не мог найти что-то подобное в библиотеках наддува, или где-нибудь еще.

Есть ли фундаментальная проблема, которая делает это невозможным?

+1

Посмотрите библиотеку Boost.Pool. 'boost :: pool_allocator' и' boost :: fast_pool_allocator' могут использоваться как распределители для 'std :: vector' и других контейнеров. –

ответ

0

Есть ли фундаментальная проблема, которая делает это невозможным?

Аргументирование поведения программы стало принципиально невозможным. Появятся всевозможные странные проблемы. Некоторые разделы кода могут выполняться или не выполняться, хотя это, похоже, не повлияет на следующие разделы, которые могут работать без помех. Некоторые разделы могут всегда терпеть неудачу. Работа со стандартной библиотекой или любой другой сторонней библиотекой станет чрезвычайно сложной. Во время выполнения могут быть фрагментации, а иногда и нет.

+3

Err .. как так? Библиотека, которая не может справиться с сбоями распределения памяти, является плохой библиотекой. –

+0

Перегрузка глобальных 'new' и' delete' - это плохая идея. В целом. Причины, как я описал. ОП сказал, что в случае отсутствия памяти исключаются исключения.Обратите внимание, что это не означает, что исчерпание памяти в пуле для одной области действия обязательно влияет на пул, определенный для следующей области. – dirkgently

2

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

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

Разум-написание собственного распределителя памяти не для слабонервных. Вы можете взглянуть на Doug Lea's malloc, который предоставляет «пространства памяти», которые можно каким-то образом использовать в своей области обзора.

+2

IMHO, что OP хочет точно настроить распределители по всей видимости (возможно, чтобы он мог покончить с необходимостью писать разные распределители и создавать специализированные контейнеры STL). YMMV. – dirkgently

+0

Как правило, я бы посоветовал не пытаться использовать контейнеры STL с внутренними программами выделения памяти. Есть очень хорошие аргументы в отношении написания собственных систем распределения памяти, но они также имеют довольно высокую стоимость. (Да, способ, которым я их использую, заключается в настройке поведения распределителя независимо от того, что его поражает, но да нет стандартных контейнеров и не используется семейство функций 'new',' delete' или 'malloc'.) –

+0

@ dirkgently: вы правы. – StackedCrooked

1

Я отвечу на другой вопрос. Посмотрите на «эффективную книгу С ++». Одна из вещей, которые они обсуждают, заключается в реализации такого рода вещей. Это было для веб-сервера

Для этой конкретной цели вы можете либо запутаться на уровне C++, переопределив новые и предоставив пользовательские распределители в STL.

Или вы можете месиво на уровне таНоса, начните с пользовательским таНосом и работать оттуда (как пооддержки)

+0

Вы имеете в виду это? -> http://www.amazon.com/Efficient-C-Performance-Programming-Techniques/dp/0201379503 –

+0

да (C++) от Bulka и Mayhew – pm100

3

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

0

Если умысел состоит в том, что все распределения внутри этой области действия происходят с этим объектом-распределителем, то это по существу локальная переменная потока.

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

(Конечно, вам необходимо пройти второй аргумент шаблона, например vector< int, UseScopedPool >.)

Смежные вопросы