2012-05-11 3 views
2

내 목표는 boost :: interprocess :: managed_shared_memory를 사용하여 공유 메모리의 맵에 주어진 데이터 구조를 저장할 수있는 SharedMemory라는 템플릿 싱글 톤 클래스를 만드는 것입니다.boost :: interprocess :: managed_shared_memory 프로그램이 충돌 함

#ifndef SHARED_MEMORY_H_ 
#define SHARED_MEMORY_H_ 

#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/containers/map.hpp> 
#include <boost/interprocess/allocators/allocator.hpp> 
#include <functional> 
#include <string> 
#include <utility> 
#include <map> 

using namespace boost::interprocess; 

template<typename T> 
class SharedMemory { 
    typedef std::pair<std::string, T> ValueType; 
    typedef allocator<ValueType, managed_shared_memory::segment_manager> 
    ShmemAllocator; 
    typedef map<std::string, T, std::less<std::string>, ShmemAllocator> SharedMap; 

    public: 
    static SharedMemory<T>& instance(); 
    void Create(); 
    void Destory(); 
    void insert(T* t); 
    std::map<std::string, T> getMapOfRecords(); 
    private: 
    SharedMemory(); 
    ~SharedMemory(){delete m_segment;} 
    void Initialize(); 
    managed_shared_memory* m_segment; 
    std::size_t m_size; 
}; 

template<typename T> 
inline void SharedMemory<T>::Create() { 
    Destory(); 
    m_segment = new managed_shared_memory(create_only, T::memory(), m_size); 
    ShmemAllocator alloc_inst (m_segment->get_segment_manager()); 
    m_segment->construct<SharedMap>("SageMap")(std::less<std::string>(), alloc_inst); 
} 

template<typename T> 
inline void SharedMemory<T>::Destory() { 
    shared_memory_object::remove(T::memory()); 
} 

template<typename T> 
inline SharedMemory<T>& SharedMemory<T>::instance() { 
    static SharedMemory<T> instance; 
    return instance; 
} 

template<typename T> 
inline SharedMemory<T>::SharedMemory() 
    : m_size(65536) { 

} 

template<typename T> 
inline void SharedMemory<T>::insert(T* t) { 
    SharedMap* mymap = m_segment->find<SharedMap>("SageMap").first; 
    mymap->insert(std::pair<std::string, T>(t->key(), *t)); 
} 

template<typename T> 
inline std::map<std::string, T> SharedMemory<T>::getMapOfRecords() { 
    SharedMap* mymap = m_segment->find<SharedMap>("SageMap").first; 
    return std::map<std::string, T>(mymap->begin(), mymap->end()); 
} 
#endif 

다음은 그 사용 예입니다.

position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::get_pointer() Line 81 + 0x1a bytes C++ 
position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::get() Line 153 + 0x16 bytes C++ 
position_monitor_eu.exe!boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > >(const boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > > & ptr={...}) Line 117 + 0x16 bytes C++ 
position_monitor_eu.exe!boost::intrusive::compact_rbtree_node_traits_impl<boost::interprocess::offset_ptr<void> >::get_left(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> > const > n={...}) Line 124 + 0x17 bytes C++ 
position_monitor_eu.exe!boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::offset_ptr<void> >,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>,1>,0,boost::intrusive::default_tag,3>,boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type>,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::container::containers_detail::select1st<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type> > >,boost::container::containers_detail::rbtree_node<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::offset_ptr<void> > >,unsigned int,1> >::begin() Line 273 + 0x42 bytes C++ 
position_monitor_eu.exe!boost::container::containers_detail::rbtree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type>,boost::container::containers_detail::select1st<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,simple_type> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::interprocess::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void>,0>,boost::interprocess::iset_index> > >::begin() Line 493 + 0x28 bytes C++ 
position_monitor_eu.exe!boost::container::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,boost::interprocess::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,simple_type>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void>,0>,boost::interprocess::iset_index> > >::begin() Line 245 + 0x1a bytes C++ 
position_monitor_eu.exe!SharedMemory<simple_type>::getMapOfRecords() Line 68 + 0x1e bytes C++ 
position_monitor_eu.exe!main(int argc=2, char * * argv=0x02b03db8) Line 200 + 0xc bytes C++ 
position_monitor_eu.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C 
position_monitor_eu.exe!mainCRTStartup() Line 371 C 
kernel32.dll!77003677()  
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll] 
ntdll.dll!775cc002()  
ntdll.dll!775cbfd5()  

나의 현재 문제가 getMapOfRecords()에서 mymap->begin()에 대한 호출에 프로그램이 충돌입니다 : 여기

#include <boost/lexical_cast.hpp> 
#include <cstring> 
#include <cstdlib> 
#include <string> 
#include <iostream> 
#include <functional> 
#include <utility> 
#include "SharedMemory.hpp" 

struct simple_type { 
    int i; 
    std::string key() {return boost::lexical_cast<std::string>(i);} 
    static const char* memory() {return std::string("simple_memory_page").c_str();} 
    simple_type(int i): i(i){} 
}; 

int main(int argc, char *argv[]) 
{ 
    if(argc == 1) { 
    SharedMemory<simple_type>& test = SharedMemory<simple_type>::instance(); 
    test.Create(); 
    test.insert(new simple_type(1)); 
    test.insert(new simple_type(2)); 
    std::string s(argv[0]); s += " child "; 
    if(0 != std::system(s.c_str())) 
     return 1; 
    test.Destory(); 
    } else { 
    SharedMemory<simple_type>& test = SharedMemory<simple_type>::instance(); 
    std::map<std::string, simple_type> records = test.getMapOfRecords(); 
    for(auto it = records.begin(); it != records.end(); ++it) { 
     std::cout << it->second.i << std::endl; 
    } 
    } 
    return 0; 
} 

는 스택 추적입니다.

+0

이 헤더를 사용하고 충돌을 나타내는 최소한의 프로그램을 보여줄 수 있습니다. 또한 프로그램의 단일 인스턴스와 충돌이 발생했는지 아니면 실제로 충돌을 일으키기 위해 적극적으로 공유해야하는지 알려주십시오. 마지막으로 플랫폼 세부 정보와 스택 추적이 유용 할 수 있습니다. –

+0

@Michael Burr : 이것은 Windows 7에서 VS2010으로 컴파일되었습니다. – andre

+0

작동하도록했습니다. 이 문제는'static const char * memory() {std :: string ("simple_memory_page")를 반환합니다 .c_str();}'정적 const char * 메모리()로 바뀌어야합니다 {return "simple_memory_page"; }'왜 그 이유를 설명 할 수 있습니까? – andre

답변

5

std::string 유형을 공유 메모리에 두는 것처럼 보입니다. 공유 메모리가 비공유 메모리를 할당하기 때문에 작동하지 않습니다. <boost/interprocess/containers/string.hpp> 대신 boost::interprocess::basic_string 유형을 사용해야합니다. here에 문자열을 넣는 예제가 있습니다. 문자열이 파괴 된 후 위의 코멘트에 무엇을 요구에 대답하기 위해


string::c_str()에 의해 반환되는 값은 무효가됩니다. 즉, memory()에 의해 반환 된 포인터에 액세스하면 정의되지 않은 동작이 발생합니다.

+0

공유 메모리에서 문자열이 아닌' '의'map'을 사용하고 있습니다. 그것은 현재 나를 위해 잘 작동합니다. – andre

+0

@ahenderson 문자열이 아니십니까? 'std :: string'을지도의 키로 사용하고 있습니다. 그리고 하나의 특정 테스트에서 작동한다고해서 그것이 항상 의미한다는 것을 의미하지는 않습니다. – interjay

+0

답변 주셔서 감사합니다. 시간을내어 답변 해 주셔서 감사합니다. 내가지도 키로 std :: string을 가질 수 없다는 가정에 한 가지 문제가 있습니다. 이 경우지도의 값은 프로세스 간 컨테이너 호환 유형이어야합니다. 이것은지도를 매우 제한하는 것으로 보입니다. 할당 자 유형을 작성하여 맵에서 사용할 수있는 것으로 의심됩니다. 나는이 문제를 이해하기 위해 더 많은 연구를해야 할 것이다. – andre

1

interjay가 string :: c_str()에 대해 쓴 내용을 추가하려면 문자열 객체에 대한 첫 번째 비정규 멤버 호출 이후에 반환 된 값이 유효하지 않을 수 있습니다. 따라서 string :: resize를 호출하면 string :: c_str()에 의해 반환 된 값이 잠재적으로 무효가 될 수 있습니다.