2012-12-03 2 views
6

최근에 할당 자의 여러 인스턴스간에 공유되는 메모리 풀을 기반으로 사용자 지정 할당자를 개발하는 일이있었습니다. STL 컨테이너, SBO 및 사용자 정의 할당 자 충돌

의도

는 할당이

그러나 특히 뭔가 좀 혼란이 발생했습니다 등등 벡터, 양단 큐,지도, 문자열 기반의 컨테이너 ++ STL 및 표준 C와 호환 될 것이 었습니다. 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; 

내가 그런 용기를 인스턴스화 할 때 일 만에 구현 을 부추 항상 제공 할당을 사용하는 방법을 볼 수 없습니다를 SBO를 사용하지 마십시오. 사용자 지정 할당자를 구현하려는 의도 중 하나가 공유 메모리의 양을 컨텍스트에서 사용할 수 있기 때문에 묻습니다. 공유 메모리의 양은 SBO 제한 인 미만일 수 있습니다. 다양한 구현 중 일부가 사용할 수 있습니다.

예를 들어 나는 표준의 두 경우 : 일반적인 블록 메모리의 SBO에 어쩌면보다 작거나 같은 상위 제한을 공유하는 프로세스 당 문자열 하나를 가질 수있는 상황을 가지고 싶습니다.

은 아마 관련 : May std::vector make use of small buffer optimization?

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. 

는 이상 어떤 사람들을 위해 일을 복잡하게 보인다 공유 메모리를 기반으로하지 않는 또 다른 예를 살펴 수 있습니다. 내가 std :: basic_string 또는 std :: vector 등을 특수화하고 싶다고 말하면서, 0xMB로 할당 한 메모리를 채우는 할당자를 가지고, 기발한 것 외의 이유없이 호출하는 엔티티에 포인터를 다시 보내기 전에 말이다.

이 새 할당 자에 특수화되어 있지만 SBO를 사용하는 컨테이너는 0xAB 패턴으로 채워진 SBO 기반 메모리를 가지지 않습니다. 그래서 예를 들면 : 사용자 정의 할당자를 구현하는 의도

typedef std::basic_string<char,myfillmemallocator> stype 

stype s; 
s.resize(2); 

assert(s[0] == 0xAB); // if SBO this will fail. 

답변

4

일이, 당신은 그것으로 할 의도 무엇을 할 수

공유 메모리 환경에서 사용할 수 있도록했지만, 그것은 그들이 존재하는 이유가 아닙니다. 사실, C++ 98/03에서 basic_string을 제외하고는 에 객체 사이에 할당 된 메모리를 공유하는 것은 합법적이지 않습니다. 할당 자 객체를 공유 할 수 있으므로 같은 위치에서 메모리를 얻을 수 있습니다. 그러나 한 객체의 수정이 다른 객체에 영향을주는 것은 불법입니다. 각 인스턴스는 분리되어 있어야합니다.

copy-on-write 문자열은 시스템에서 문자에 대한 비 const 액세스가 기록되어 복사를 수행한다고 가정하기 때문에 작동합니다. 그리고 C++ 11에서는 심지어 basic_string이 이와 같이 copy-on-write-style 항목을 사용하는 것을 금지합니다.

예를 들어 내가 표준의 두 인스턴스 :: 메모리의 일반 블록을 공유하는 프로세스 당 문자열 하나를 가질 수있는 상황을 가지고 싶다되는 SBO 상한 어쩌면보다 작거나 같은.

자신의 수업을 작성하지 않으면 불가능합니다. 할당자는 메모리가 어디서 오는지만 제어합니다. 당신이 원하는 것은 보장 된 copy-on-write 문자열 또는 일종의 공유 문자열 클래스입니다.

원하는 용도로 특별히 설계된 컨테이너 클래스가 필요합니다.

+1

Nicol,하지만 단 한 가지 질문에 대해 공유 메모리를 할당하는 할당자를 가질 수 없으며 오프셋 포인터 개념을 통해 메모리의 별명을 지정할 수 없습니다. 이것은 정상적으로 수행되는 방식입니다 (boost.interprocess). 확실히 할 수없는 이유를 이해합니다. –

+2

@ 세미나 : 그 문자열을 복사하면 어떻게됩니까? 해당 문자열에 문자를 삽입하면 재 할당이 발생할 수 있습니다. 이러한 작업의 의미가 무엇인지 분명하지 않지만 한 가지 분명한 사실은 의미가 무엇이든 구현 자체가 알아야하는 의미입니다. 즉, 일을 특정 방식으로 수행하는 특정 컨테이너 구현이 필요합니다. –

+1

공유 문자열에서 다른 문자열로 복사하는 것은 일반적인 복사입니다. 대상 문자열은 공유 메모리를 가질 것으로 예상되지 않습니다. 이것은 다른 방법으로도 동일합니다. 표준 std :: string에서 공유 문자열 데이터로 복사됩니다. 특수화 된 할당 자에 의해 제공되는 공유 메모리에 저장하십시오 .- 따라서 이것은 크기 변경/추가 등과 관련된 질문 –