C++ 为什么在boost进程间共享内存中分配的对象占用的内存比需要的多?

C++ 为什么在boost进程间共享内存中分配的对象占用的内存比需要的多?,c++,boost,shared-memory,allocator,boost-interprocess,C++,Boost,Shared Memory,Allocator,Boost Interprocess,对于以下使用Boost进程间共享内存的程序 #include <iostream> #include <boost/interprocess/mapped_region.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/list.hpp> #include <iostream> #de

对于以下使用Boost进程间共享内存的程序

#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <iostream>

#define SHARED_MEMORY_NAME "SO12439099-MySharedMemory"
#define DATAOUTPUT "OutputFromObject"
#define INITIAL_MEM 650000
#define STATE_MATRIX_SIZE 4

using namespace std;
namespace bip = boost::interprocess;


class SharedObject
{
public:
    unsigned int tNumber;
    bool pRcvdFlag;
    bool sRcvdFlag;
    unsigned long lTimeStamp; 
};

typedef bip::allocator<SharedObject, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef bip::list<SharedObject, ShmemAllocator> SharedMemData; 


int main()
{
        bip::managed_shared_memory* seg;
        SharedMemData *sharedMemOutputList;

        bip::shared_memory_object::remove(DATAOUTPUT);
        seg = new bip::managed_shared_memory(bip::create_only, DATAOUTPUT, INITIAL_MEM);
        const ShmemAllocator alloc_inst(seg->get_segment_manager());
        sharedMemOutputList = seg->construct<SharedMemData>("TrackOutput")(alloc_inst);

        std::size_t beforeAllocation = seg->get_free_memory();
        std::cout<<"\nBefore allocation = "<< beforeAllocation <<"\n";
        SharedObject temp;
        sharedMemOutputList->push_back(temp);
        std::size_t afterAllocation = seg->get_free_memory();
        std::cout<<"After allocation = "<< afterAllocation <<"\n";        
        std::cout<<"Difference = "<< beforeAllocation - afterAllocation <<"\n";        
        std::cout<<"Size of SharedObject = "<< sizeof(SharedObject) <<"\n";   
        std::cout<<"Size of SharedObject's temp instance = "<< sizeof(temp) <<"\n";           
        seg->destroy<SharedMemData>("TrackOutput");
        delete seg;            
}//main
如果
SharedObject
及其实例的大小是16字节,那么分配的差异怎么可能是48?即使是自动完成的,也无法解释3倍的大小(对于较大的结构,其大小为1.33倍)。
因此,我无法可靠地分配和动态增长共享内存。如果
SharedObject
包含一个动态增长的列表,则可能会进一步增加空间分配的不确定性

如何安全地处理这些情况

ps:要运行程序,必须链接
pthread
库和
librt.so

更新:

这是我在多次运行时获得的内存使用模式(
内存增加
列基本上是
内存使用
列的当前行减去
内存使用列
的前一行):

╔═════════════╦════════════════╦═════════════════╗
║记忆║结构尺寸║记忆增加║
╠═════════════╬════════════════╬═════════════════╣
║48║1.║║
║48║4.║0║
║48║8.║0║
║48║16║0║
║64║32║16║
║64║40║0║
║80║48║16║
║96║64║32║
║160║128║64║
║288║256║128║
║416║384║128║
║544║512║128║
║800║768║256║
║1056║1024║256║
╚═════════════╩════════════════╩═════════════════╝

重要提示:上表仅适用于共享内存
列表
。对于
vector
,所使用的(内存,结构大小)值为=(48,1),(48,8),(48,16),(48,32),(80,64),(80,72),(112,96),(128,120),(176,168),(272,264),(544,528)。

因此,其他容器需要不同的内存计算公式。

请参见此处的分析和比较:

长话短说:基于节点的容器在这里不是很好

考虑使用池分配器-是的,这样堆叠分配器会有点笨拙,但它确实消除了节点分配上的巨大开销


您还可以考虑使用顺序存储,然后“在此基础上”使用Boost侵入式列表容器。Boost Intrusive可用于
进程间::偏移量ptr
,因此您可以将其用于托管内存段。

请记住,任何通用分配机制都有一个有效负载,用于存储有关如何释放该内存、如何将该缓冲区与相邻缓冲区合并等信息。。这在系统malloc中发生(通常,每次分配8-16个额外字节加上额外对齐)。共享内存中的内存分配器的开销为4-8字节(32位系统中为8-16字节,64位系统中为8-16字节)

然后库需要存储对象的数量,以便在调用“destroy_ptr(ptr)”时调用析构函数(您可以分配数组,因此需要知道应该调用多少个析构函数)。您已经进行了命名分配,因此库需要将该字符串存储在共享内存中,并使用一些元数据来查找它(一个指向该字符串的指针,可能这是一个“命名分配”,而不是“匿名”或“实例分配”)

因此,16个字节的数据+8个字节来自内存分配器+8个字节用于存储指向名称的指针+元数据+12个字节来自字符串“TrackOutput”(包括null end)再加上8个字节的对齐,就得到了48个字节

每次分配的开销几乎是恒定的。因此常数因子1.33只适用于较小的分配。如果分配一个字节,则会得到更糟糕的因子,就像从堆中分配一个字符一样

如果没有可用内存来存储新对象,库将引发异常,您可以捕获它并尝试创建新的托管共享内存。请注意,内存会随着分配和重新分配而变得碎片化,因此即使共享内存中有可用字节,托管共享内存也无法为您的请求提供服务,因为没有重叠共享内存不能自动扩展,所以碎片化是一个比堆内存更大的问题


您无法动态增长共享内存,因为其他进程可能已连接到共享内存,并且在尝试访问未映射的页时会崩溃。唯一的替代方法是预先分配一个共享内存,该内存足以添加一个常量填充因子,或者分配一个新的托管共享内存并通知所有其他读写器(可能使用原始共享内存中的预定位结构)新元素将进入一个新的托管共享内存。

请记住,如果分配一个块,分配器需要一些内存用于内务管理。但是在这种情况下,额外的内存远远大于内务管理所需的内存。没有人可以帮助共享内存吗?谢谢。按照这种逻辑,使用表单
memoryToAllocate=sizeOfStructures+16+16+stringSize+16;
的ula应该可以很好地用于32位和64位系统。分配比所需多一点的内存没有坏处。
Before allocation = 649680
After allocation = 649632
Difference = 48
Size of SharedObject = 16
Size of SharedObject's temp instance = 16