2016-06-04 4 views
1

공유 메모리를 설정하고 관리하기 위해 클래스를 사용하는 코드를 작성하려고하고 있는데, 그 클래스의 객체를 메인 프로그램에서 호출합니다. 모든 코드는 내 main()에 직접있을 때 작동하지만 클래스에서 설정하고 해당 클래스의 객체를 인스턴스화하면 segfault가 생깁니다.클래스 개체 segfaults에서 boost :: interprocess를 사용하는 이유는 무엇입니까?

이유 또는 수정 방법을 모르겠습니까?

#include <boost/interprocess/managed_shared_memory.hpp> 
using namespace boost::interprocess; 

typedef struct teststruct { 
    int  testint=9; 
}; 

typedef std::pair<teststruct, int> memsh_teststruct; 

int main(int argc, char *argv[]) 
{ 


    printf("inMain0\n"); 


    struct shm_remove 
    { 
     shm_remove() { shared_memory_object::remove("testShare"); } 
     ~shm_remove(){ shared_memory_object::remove("testShare"); } 
    } remover; 

    //Construct managed shared memory 
    managed_shared_memory segment(create_only, "testShare", 65536); 


    teststruct myTeststruct; 
    memsh_teststruct *inst_teststruct; 

    inst_teststruct = segment.construct<memsh_teststruct> 
     ("name_myTeststruct") 
     (myTeststruct, 0); 

    printf("construct_ptr: %p \n", &inst_teststruct->first); 

    inst_teststruct->first.testint = 1234; 

    printf("construct_val: %d\n", inst_teststruct->first.testint); 




    int mainInt; 

    printf("inMain1\n"); 

    mainInt = inst_teststruct->first.testint; 

    printf("mainInt: %d\n", mainInt); 

    printf("inMain2\n"); 
} 

출력은 다음과 같이 잘 보이는 :

첫 번째 예는 여기 내 main() 함수에서 문제없이 작동하는 예를 보여줍니다

construct_ptr: 0x7f0d41834118 
construct_val: 1234 
inMain0 
inMain1 
mainInt: 1234 
inMain2 

여기에서 설정하는 두 번째 예제를 정확한 공유 메모리이지만 클래스를 사용합니다.

#include <boost/interprocess/managed_shared_memory.hpp> 
using namespace boost::interprocess; 

typedef struct teststruct { 
    int  testint=9; 
}; 


typedef std::pair<teststruct, int> memsh_teststruct; 

class testclass{ 
    public: 
     testclass(); 
     bool something(int in); 

     teststruct myTeststruct; 
     memsh_teststruct *inst_teststruct; 
}; 



testclass::testclass() 
{ 
    struct shm_remove 
    { 
     shm_remove() { shared_memory_object::remove("testShare"); } 
     ~shm_remove(){ shared_memory_object::remove("testShare"); } 
    } remover; 

    //Construct managed shared memory 
    managed_shared_memory segment(create_only, "testShare", 65536); 

    inst_teststruct = segment.construct<memsh_teststruct> 
     ("name_myTeststruct") 
     (myTeststruct, 0); 

    printf("construct_ptr: %p \n", &inst_teststruct->first); 

    inst_teststruct->first.testint = 1234; 

    printf("construct_val: %d\n", inst_teststruct->first.testint); 
} 



int main(int argc, char *argv[]) 
{ 

    printf("inMain0\n"); 

    int mainInt; 
    testclass testclassObj; 

    printf("inMain1\n"); 

    mainInt = testclassObj.inst_teststruct->first.testint; 

    printf("mainInt: %d\n", mainInt); 

    printf("inMain2\n"); 
} 

그러나이 두 번째 예 세그먼테이션 폴트 (segfault), 이것은 출력 :

inMain0 
construct_ptr: 0x7fa222d37118 
construct_val: 1234 
inMain1 
Segmentation fault (core dumped) 

... 왜 주에서

mainInt = testclassObj.inst_teststruct->first.testint; 

()에 대한 호출이 segfault의 원인이 무엇입니까?

공유 메모리 변수와 상호 작용하도록 다른 클래스를 정의하는 등 다른 변형도 시도해 보았습니다. 또한 segfaults도 있습니다.

무슨 일이 일어나고 있는지 추측해야한다면, 아마도 testclass() 생성자를 빠져 나온 후에 공유 메모리가 닫히는 것처럼 느껴집니다. 그러나, 나는 이것을 피할 수있는 적절한 방법을 모르기 때문에, 전체 testclassObj 객체가 정리 될 때 main()에서 리턴 할 때 공유 메모리가 대신 닫히게된다.

반면에, 내가 틀렸을 수도 있습니다.

감사합니다, B

편집 : EDIT2 : 마지막 편집 제거, 내 오류가 무관 인해 내가 그의 대답에 숀와 스레드를 언급 점에서했던 바보 같은 일이었다.

답변

1

예상 한대로 공유 메모리가 예상대로 종료됩니다.

testclass::testclass에 생성되고 공유 메모리를 닫고 있지만 공유 메모리가 어디에 사용되었는지 가리키는 채로 inst_teststruct 인 생성자 끝의 범위를 벗어납니다.

포인터가있는 한 segment 주위에 두어야합니다. , 가장 공유 메모리의 수명을 관리하는 방법에 어떤 생각을해야합니다,

class testclass { 
public: 
    testclass(); 

    managed_shared_memory segment; 
    teststruct myTeststruct; 
    memsh_teststruct *inst_teststruct; 
}; 

testclass::testclass() 
    : segment(create_only, "testShare", 65536) //< Construct managed shared memory 
{ 
    struct shm_remove { 
     shm_remove() { shared_memory_object::remove("testShare"); } 
     ~shm_remove() { shared_memory_object::remove("testShare"); } 
    } remover; 

    inst_teststruct = segment.construct<memsh_teststruct> 
     ("name_myTeststruct") 
     (myTeststruct, 0); 

    printf("construct_ptr: %p \n", &inst_teststruct->first); 

    inst_teststruct->first.testint = 1234; 

    printf("construct_val: %d\n", inst_teststruct->first.testint); 
} 

그러나 : 그 작업을 수행하는 가장 쉬운 방법은 testclass 그래서 등의 클래스 멤버로 segment을 들어 올릴 아마 특히 다른 프로세스가 관련되어있을 때 그렇습니다.

+0

감사합니다. Sean은 아직 테스트하지 않았지만 의미가 있습니다.내가 정의한 경우 소멸자에서 제거제를 특별히 호출하는 방법이 있습니까? 구조체 shm_remove가 라이브러리에 의해 처리되는 방법을 완전히 이해하지 못한다. 그러나 볼 수있는 한 손대지 않았지만 분명히 암묵적인 기능이있다. – brneuro

+0

당신의 대답은 회상에서 정말 분명합니다. 세그먼트가 managed_shared_memory 유형의 변수라는 사실을 놓쳤습니다. – brneuro

+0

명시 적으로 제거 호출에 대한 내 질문에 대한 답변은 여기에 있습니다. http://stackoverflow.com/questions/18130781/boost-removing-managed-shared-memory-when-process-is-attached – brneuro