It seems you’re simply running out of memory. You might reason that you shouldn’t since the individual allocations don’t occupy the amount of space.
But memory fragmentation can do this: if there is sufficient ‘padding’ or ‘overhead’ with the shared memory objects, you can run out of contiguously allocatable space.
Either, store your data in a pre-allocated vector (e.g.), or use one of the smarter interprocess allocation algorithms:
The simplest way to resolve it in this instance would seem to be just making the shared memory area twice as big (minimal size is a 4K memory page on most systems, anyway).
I just used 2*size
and the tests ran to completion.
Update/fixes
I’ve just verified that indeed doing things “the vector way” is much more efficient: replacing std::map
by boost’s flat_map
gets you vector storage.
The big difference is that each node in a map is dynamically allocated, incurring a fixed overhead, linearly consuming available memory.
Observations
- There’s considerable initial overhead, consuming 320 bytes before anything happened.
- with the
flat_map
, you also reserve the vector capacity up front, you see that you can win just a little extra storage efficiency.
The above graph was created from the output of the following program. Look for the calls to get_free_memory()
. To switch map
implementation, just change #if 0
into #if 1
. (Note how I cleaned up some of the code that was needless repetitious and using exceptions for flow control).
#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 << "https://stackoverflow.com/" << 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";
}
}