Bad alloc is thrown

后端 未结 1 599
醉话见心
醉话见心 2020-12-02 02:41

I am getting a \'bad_alloc while trying to work with boost managed shared memory. I\'ve copied the boost example from their quick guide for the impatient and incorporated my

相关标签:
1条回答
  • 2020-12-02 03:04

    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:

    • http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/allocators_containers.html

    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 << " / " << 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";
        }
    }
    
    0 讨论(0)
提交回复
热议问题