STL容器,SBO和自定义分配器冲突

7 c++ optimization stl shared-memory allocator

我最近一直在努力开发基于内存池的自定义分配器,它在分配器的多个实例之间共享.

目的是分配器与STL和基于标准C++的容器兼容,例如vector,deque,map,string等

然而,特别是某些事情让我有些困惑.容器的各种实现(例如std :: vector,std :: string)使用小缓冲区优化 - 基于堆栈的分配用于小的初始内存需求.

例如,MSVC9.1在basic_string类中具有以下成员:

union _Bxty
{   // storage for small buffer or pointer to larger one
   _Elem _Buf[_BUF_SIZE];
   _Elem *_Ptr;
   char _Alias[_BUF_SIZE];  // to permit aliasing
} _Bx;
Run Code Online (Sandbox Code Playgroud)

我无法看到在实例化这样的容器时,如何只能实现并始终使用提供的分配器而不使用SBO.我问,因为实现自定义分配器的意图之一是能够在共享内存上下文中使用它们,其中共享内存的数量可能小于各种实现可能使用的SBO限制.

例如,我想有一种情况,我可以有两个std :: string实例,每个进程共享一个公共内存块,可能小于或等于SBO上限.

可能相关:5月std :: vector使用小缓冲区优化?

typedef std::vector<int,mysharedmemallocator> shmvtype;

shmvtype v(2,0); //<-- if SBO then error as memory is allocated on
                 //stack not via the allocator

v[1] = 1234;  //<-- if SBO then error as wrong piece of memory
              // is being modified.
Run Code Online (Sandbox Code Playgroud)

让我们看看另一个不基于共享内存的示例,因为它似乎使某些人的事情复杂化.让我说我想专门化我的std :: basic_string或std :: vector等一个分配器,它在将指针呈现给调用实体之前填充它分配的值为0xAB,而不是奇思妙想.

专门使用此新分配器但也使用SBO的容器将不会使其基于SBO的内存填充0xAB模式.例如:

typedef std::basic_string<char,myfillmemallocator> stype

stype s;
s.resize(2);

assert(s[0] == 0xAB); // if SBO this will fail.
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 5

实现自定义分配器的意图之一是能够在共享内存上下文中使用它们

这可能是你打算用它做的,但这并不是它们存在的原因.实际上,除了basic_string在C++ 98/03中,在对象之间共享分配的内存是不合法的.他们可以共享分配器对象,因此他们可以从同一个地方获取内存.但修改一个对象以影响另一个不相关的对象是违法的; 每个实例必须是分开的.

写时复制字符串仅起作用,因为系统假定对字符的任何非const访问都将写入,从而执行复制.在C++ 11中,甚至basic_string禁止像这样写入copy-on-write风格的东西.

例如,我想有一种情况,我可以有两个std :: string实例,每个进程共享一个公共内存块,可能小于或等于SBO上限.

没有写自己的课,这是不可能的.分配器仅控制内存的来源.你想要的是一个有保证的写时复制字符串或某种共享字符串类.

您想要的是需要专门为此目的设计的容器类.

  • @Seminar:如果你复制那个字符串怎么办?如果将字符插入该字符串会发生什么情况,从而可能导致重新分配?目前尚不清楚任何这些操作的语义应该是什么,但有一点是清楚的:无论语义是什么,它们都是实现本身需要了解的语义.也就是说,您需要一个以特定方式执行某项操作的特定容器实现. (2认同)