2017-12-10 17 views
1

공유 메모리를 사용하여 프로세스 간 통신이 필요하며 공유 메모리 파일 설명자 또는 공통 파일 설명자 주소를 구조체 또는 벡터/맵을 가리키는 포인터에 할당 할 수 있습니까? 공유 메모리의 주소파일 디스크립터의 주소를 변수에 할당 할 수 있습니까?

Struct A{...}; 
A* stru = static_cast<A*>(addr); // is this OK? 
+0

'A'가 POD이고 'addr'이 어떻게 정렬되는지에 달려 있다고 생각합니다. – melpomene

답변

0

먼저 예를 들어

, addr, 당신은 아마 Boost.interprocess보고를 사용해야합니다.

수동 방식의 경우 계속 읽으십시오.

이렇게하려면 구조체에 포인터를 사용하면 안됩니다. 또한 가상 기능이 없어야합니다. 단지 포인터가 아닌 데이터 멤버가있는 구조체 (기본 제공 형식을 의미하며 std::string 또는 std::vector 또는 일반 구조체가 아닌 요소) 및 해당 멤버 함수 (있는 경우)는 해당 데이터에서만 작동하며 비 멤버 함수를 호출하면 안전 할 수 있습니다.

주소가 올바르게 정렬되어 있는지 확인해야합니다.

#include <cstdint> 
#include <cassert> 
// ... 

assert(reinterpret_cast<std::uintptr_t>(addr) % alignof(A) == 0); 

당신이 공유 메모리를 생성하는 데 사용하는 방법은 당신이 바이트 단위로 원하는 정렬을 지정할 수 있습니다 경우

는 다음 alignof(A) 당신에게 정확한 바이트 수를 줄 것이다 : 당신은 명시 적으로 확인할 수 있습니다.

메모리의 크기는 (적어도 sizeof(A)해야합니다.)

호환 정렬 및 크기의 경우, 다음의 새로운 배치를 사용하여 해당 메모리의 개체를 만들어야합니다 충분히 커야합니다

#include <new> 
// ... 

auto stru = new(addr) A; 

struaddr이 가리키는 메모리에 객체를 만듭니다.

해당 개체에 delete으로 전화하지 마십시오. 일반적 delete를 호출하는 위치에서, 당신은 대신 수동으로 소멸자를 호출해야합니다 :

이 쉽게, 당신은 아마 소멸자를 호출하는 사용자 정의 람다 Deleter가 함께 unique_ptr에서이 객체를 포장해야하기 위해서는
stru->~A(); 

:

#include <memory> 
// ... 

auto a_dtor_caller = [](A* obj){ obj->~A(); }; 
auto stru = std::unique_ptr<A, decltype(a_dtor_caller)>(new(addr) A, a_dtor_caller); 

stru 지금있는 unique_ptr하고 범위를 벗어나면가 관리하는 A 인스턴스가 제대로 파괴 될 것이다.

위의 내용은 한 번만 수행해야합니다. 단지 개체에 액세스해야하는 다른 프로세스는 사용해야합니다

A* stru = static_cast<A*>(addr); 

그것은 그들도 결코 delete 목적이나 그 소멸자를 호출 할 수있는 것은 물론이다. 객체를 관리하는 unique_ptr만이 그렇게해야합니다.

공유 메모리를 확보하려고 할 때 먼저 객체를 파괴해야합니다.코드를 자연스럽게 공유 메모리를 해제하기 전에 unique_ptr은 "만료"는, 그럼 당신이 수동으로 수행해야합니다하지 않는 경우

stru.reset(); 

이 개체를 소멸하고 stru 효과적으로 지금 nullptr이다.

전체적으로 나는 Boost.interprocess를 대신 권장합니다. 오류가 발생하기 쉽습니다.

+0

고마워, 그냥 공유 메모리를 닫고 '삭제'할 때 s = NULL로 만들 수 있습니까? – maidamai

+0

@maidamai 공유 메모리를 해제하기 전에 객체를 파괴하는 방법에 대한 대답을 업데이트했습니다. –

+0

@maidamai 일반 구조체에 대해서만이 작업을 안전하게 수행 할 수 있음을 언급하는 것을 잊어 버렸습니다. 대답에 새로 추가 된 첫 번째 단락을 참조하십시오. –