【问题标题】:Bad alloc is thrown抛出了错误的分配
【发布时间】:2014-02-12 18:16:20
【问题描述】:

在尝试使用 boost 托管共享内存时,我得到了一个“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

【问题讨论】:

    标签: c++ memory boost bad-alloc


    【解决方案1】:

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

    但内存碎片可以做到这一点:如果共享内存对象有足够的“填充”或“开销”,您可能会用完连续分配的空间。

    要么将数据存储在预先分配的向量中(例如),要么使用更智能的进程间分配算法之一:

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

    我刚刚使用了2*size,测试运行完成。

    更新/修复

    我刚刚验证了确实以“向量方式”做事更有效率:用 boost 的 flat_map 替换 std::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";
        }
    }
    

    【讨论】:

    • 是的,我也可以确认一下。只需使用 2*size 就可以了。
    • 我也试过了,它的工作原理。我认为额外的 1000 大小足以支付开销。不,我不觉得自己很愚蠢。谢谢!
    • 我刚刚添加了漂亮的图表并与boost::flat_map 进行了比较。你会觉得这很有趣。
    • 感谢您这样做!一切似乎对我的测试程序(上面的那个)都很好,但是,我正在处理的项目不起作用。它在插入语句处崩溃。
    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多