错误的分配被抛出

2021-12-21 00:00:00 memory c++ boost bad-alloc

我在尝试使用 boost 托管共享内存时遇到了bad_alloc".我已经从他们的快速指南中复制了 boost 示例,并结合了我自己的更改.我的代码在下面,我已经注释掉了示例内容并在下面写了我自己的代码.我还投入了一些调试和测试的东西.

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 own changes. MY code is below, I've commented out the example stuff and wrote my own below it. I've also put in some debugging and testing stuff.

有人有什么想法吗?非常感谢任何帮助!

Does anyone have any ideas? Any help is greatly appreciated!

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


Starting the program.


";

//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 
";
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.
";
            }
            catch(boost::interprocess::interprocess_exception &ex){
                std::cout << "
Certificates object wont load
";
                mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
            }
        }

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

    std::cout << "

Done Inserting
Starting output
.";
    /*    
        //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) << "
";

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

            try{
                mymap = shm_segment.find<certSHMMap>(elementName).first;   //object name
            }
            catch(boost::interprocess::interprocess_exception &ex){
                std::cout << "Certificates object wont load
";
                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 << "
 shm space wont load wont load
";
    std::cout << "
 Why: " << ex.what() << "
";


}
shared_memory_object::remove(space_name);
return 0;

}

这是我的程序输出...

And here is my program output...

 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

推荐答案

看来您只是内存不足.您可能会认为您不应该这样做,因为各个分配不占用空间量.

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

在这种情况下解决它的最简单方法似乎是将共享内存区域扩大一倍(无论如何,在大多数系统上,最小大小是 4K 内存页).

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).

我刚刚使用了 2*size 并且测试运行完成.

I just used 2*size and the tests ran to completion.

我刚刚证实,确实以矢量方式"做事效率更高:用 boost 的 flat_map 替换 std::map 可以获得矢量存储.

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.

观察

  • 初始开销很大,在发生任何事情之前消耗了 320 个字节.
  • 使用 flat_map,您还可以预先保留矢量容量,您会发现您可以赢得一点额外的存储效率.
  • 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.

上图是根据以下程序的输出创建的.查找对 get_free_memory() 的调用.要切换map 实现,只需将#if 0 更改为#if 1.(注意我是如何清理一些不必要的重复代码并使用异常进行流量控制的).

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


Starting the program.


";

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

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

    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() << "
";

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

        std::cout << "

Done Inserting
Starting output
";

        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 << "
";
        }
    }
    catch(boost::interprocess::interprocess_exception &ex){
        std::cout << "
 shm space wont load wont load
";
        std::cout << "
 Why: " << ex.what() << "
";
    }
}

相关文章