Bad alloc is thrown

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.

enter image description here

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";
    }
}

Leave a Comment