Плохое размещение

Я получаю bad_alloc при попытке работать с общей управляемой памятью boost. Я скопировал пример поддержки из их краткого руководства для нетерпеливых и включил свои собственные изменения. Мой код приведен ниже, я прокомментировал пример и написал свой собственный ниже. Я также добавил кое-что для отладки и тестирования.

У кого-нибудь есть какие-либо идеи? Любая помощь очень ценится!

-M

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/exceptions.hpp>

#include <functional>
#include <utility>
#include <iostream>
#include <string>

#define space_name "MySharedMemorydfgdfhgd"namespace std{}

int main ()
{

using namespace boost::interprocess;//Remove shared memory on construction and destruction

struct shm_remove
{
shm_remove() { shared_memory_object::remove(space_name); }
~shm_remove(){ shared_memory_object::remove(space_name); }
} remover;

typedef int    KeyType;
typedef boost::interprocess::managed_shared_memory::allocator<char>::type char_allocator;
//typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> char_allocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, char_allocator> shm_string;

struct certificateStorage{
int certificate_id;
certificateStorage( int _certificate_id, const char* _certificate, const char* _key, const char_allocator &al) :
certificate_id(_certificate_id)
{}
};

//Note that map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
//so the allocator must allocate that pair.

//typedef std::pair<const int, float> ValueType;
typedef std::pair<const int, certificateStorage> certValueType;
//typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;
typedef allocator<certValueType, boost::interprocess::managed_shared_memory::segment_manager> certShmemAllocator;
//typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> MyMap;
typedef map<KeyType, certificateStorage, std::less<KeyType>, certShmemAllocator> certSHMMap;
// typedef boost::interprocess::map<KeyType, int, std::less<KeyType>, certShmemAllocator> certSHMMap;

std::cout << "\n\n\nStarting the program.\n\n\n";

//Shared memory front-end that is able to construct objects
//associated with a c-string. Erase previous shared memory with the name
//to be used and create the memory segment at the specified address and initialize resources

const int numentries = 20;
const char* elementName = "mymap";
int size = sizeof(certificateStorage) * numentries + 1000;
std::cout << "SHM size is " <<size<< " bytes \n";
int runningsize = 0;try{
//this stayed the same
managed_shared_memory shm_segment
(create_only
,space_name//segment name
,size);

certSHMMap *mymap;

//Initialize the shared memory STL-compatible allocator
//ShmemAllocator alloc_inst (segment.get_segment_manager());
certShmemAllocator alloc_inst (shm_segment.get_segment_manager());
char_allocator ca(shm_segment.get_allocator<char>());

for(int i = 0; i < numentries; i++){

try{
//MyMap *mymap =
// segment.construct<MyMap>("MyMap")      //object name
//(std::less<int>() //first  ctor parameter
//  ,alloc_inst);     //second ctor parameter

mymap = shm_segment.construct<certSHMMap>(elementName)
(std::less<int>()
,alloc_inst);     //object name
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "Certificates element already exists.";

try{
mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
std::cout << " Fetching existing pointer.\n";
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "\nCertificates object wont load\n";
mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
}
}

certificateStorage thisCert(i, "", "", ca);
std::cout << "Created object.\n";
mymap->insert(certValueType(i, thisCert));
std::cout << "Inserted object. " << i <<" size is " <<sizeof(thisCert)  << " \n";
runningsize += sizeof(thisCert) ;
std::cout << "SHM Current size is " << runningsize << " / " << size << "\n";
}

std::cout << "\n\nDone Inserting\nStarting output\n.";
/*
//Insert data in the map
for(int i = 0; i < 100; ++i){
mymap->insert(std::pair<const int, float>(i, (float)(i*i)));
}

for(int i = 0; i < 100; ++i){
std::cout << "Key: " << i << " Value: " << mymap->at(i) << "\n";

mymap->insert(std::pair<const int, float>(i, (float)(i*2)));
} */for(int i = 0; i < numentries; i++){

try{
mymap = shm_segment.construct<certSHMMap>(elementName)(std::less<int>() ,alloc_inst);     //object name
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "Certificates element already exists.\n";

try{
mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "Certificates object wont load\n";
mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
}
}
certificateStorage tmp = mymap->at(i);
std::cout << "The key is: " << i << " And the value is: " << tmp.certificate_id;
}
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "\n shm space wont load wont load\n";
std::cout << "\n Why: " << ex.what() << "\n";}
shared_memory_object::remove(space_name);
return 0;

}

И вот мой вывод программы …

 Starting the program.SHM size is 1080 bytes
Created object.
Inserted object. 0 size is 4
SHM Current size is 4 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 1 size is 4
SHM Current size is 8 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 2 size is 4
SHM Current size is 12 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 3 size is 4
SHM Current size is 16 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 4 size is 4
SHM Current size is 20 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 5 size is 4
SHM Current size is 24 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 6 size is 4
SHM Current size is 28 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 7 size is 4
SHM Current size is 32 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 8 size is 4
SHM Current size is 36 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 9 size is 4
SHM Current size is 40 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 10 size is 4
SHM Current size is 44 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 11 size is 4
SHM Current size is 48 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 12 size is 4
SHM Current size is 52 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 13 size is 4
SHM Current size is 56 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 14 size is 4
SHM Current size is 60 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.
Inserted object. 15 size is 4
SHM Current size is 64 / 1080
Certificates element already exists. Fetching existing pointer.
Created object.

shm space wont load wont load

Why: boost::interprocess::bad_alloc

3

Решение

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

Но фрагментация памяти может сделать это: если имеется достаточное «заполнение» или «накладные расходы» с объектами общей памяти, вы можете исчерпать непрерывно распределяемый пространство.

Либо сохраняйте свои данные в предварительно выделенном векторе (например), либо используйте один из более интеллектуальных алгоритмов распределения между процессами:

В данном случае самым простым способом решения этой проблемы, по-видимому, было бы просто сделать область разделяемой памяти в два раза больше (во всяком случае, на большинстве систем минимальный размер страницы памяти составляет 4 КБ).

Я просто использовал 2*size и испытания подошли к завершению.

Обновление / исправление

Я только что проверил, что действительно делать вещи «векторным путем» гораздо эффективнее: заменять std::map бустом flat_map получает вам векторное хранилище.

Большая разница в том, что каждый узел на карте выделяется динамически, что приводит к фиксированным издержкам и линейному потреблению доступной памяти.

введите описание изображения здесь

наблюдения

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

Приведенный выше график был создан на основе результатов следующей программы. Ищите звонки get_free_memory(), Переключать map реализация, просто изменить #if 0 в #if 1, (Обратите внимание, как я очистил часть кода, который был ненужным повторением и использовал исключения для управления потоком).

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/flat_map.hpp>
#include <boost/interprocess/exceptions.hpp>

#include <functional>
#include <utility>
#include <iostream>
#include <string>

#define space_name "MySharedMemory"
int main ()
{
using namespace boost::interprocess;
//Remove shared memory on construction and destruction

struct shm_remove
{
shm_remove() { shared_memory_object::remove(space_name); }
~shm_remove(){ shared_memory_object::remove(space_name); }
} remover;

typedef int KeyType;
typedef boost::interprocess::managed_shared_memory::allocator<char>::type char_allocator;
//typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> char_allocator;
//typedef boost::interprocess::basic_string<char, std::char_traits<char>, char_allocator> shm_string;

struct certificateStorage{
int certificate_id;
certificateStorage( int _certificate_id, const char* _certificate, const char* _key, const char_allocator &al) :
certificate_id(_certificate_id)
{}
};

#if 0 // STL
typedef std::pair<const int, certificateStorage> certValueType;
typedef allocator<certValueType, boost::interprocess::managed_shared_memory::segment_manager> certShmemAllocator;
typedef map<KeyType, certificateStorage, std::less<KeyType>, certShmemAllocator> certSHMMap;
#else // FLAT_MAP
typedef std::pair<int, certificateStorage> certValueType; // not const key for flat_map
typedef allocator<certValueType, boost::interprocess::managed_shared_memory::segment_manager> certShmemAllocator;
typedef boost::container::flat_map<KeyType, certificateStorage, std::less<KeyType>, certShmemAllocator> certSHMMap;
#endif

std::cout << "\n\n\nStarting the program.\n\n\n";

const int numentries    = 20;
const char* elementName = "mymap";
int size                = sizeof(certificateStorage) * numentries + 1000;
int runningsize         = 0;

std::cout << "SHM size is " <<size<< " bytes \n";

try{
managed_shared_memory shm_segment(create_only, space_name/*segment name*/, size);

certShmemAllocator alloc_inst (shm_segment.get_segment_manager());
char_allocator ca(shm_segment.get_allocator<char>());

certSHMMap *mymap = shm_segment.find_or_construct<certSHMMap>(elementName)
(std::less<int>(), alloc_inst);

mymap->reserve(numentries);

for(int i = 0; i < numentries; i++){
std::cout << "Free memory: " << shm_segment.get_free_memory() << "\n";

certificateStorage thisCert(i, "", "", ca);
std::cout << "Created object.\n";
mymap->insert(certValueType(i, thisCert));
std::cout << "Inserted object. " << i <<" size is " <<sizeof(thisCert)  << " \n";
runningsize += sizeof(thisCert) ;
std::cout << "SHM Current size is " << runningsize << " / " << size << "\n";
}

std::cout << "\n\nDone Inserting\nStarting output\n";

for(int i = 0; i < numentries; i++){
certificateStorage tmp = mymap->at(i);
std::cout << "The key is: " << i << " And the value is: " << tmp.certificate_id << "\n";
}
}
catch(boost::interprocess::interprocess_exception &ex){
std::cout << "\n shm space wont load wont load\n";
std::cout << "\n Why: " << ex.what() << "\n";
}
}
8

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector