2012-05-11 115 views
2

我的目標是創建一個名爲SharedMemory的模板單例類,它可以使用boost :: interprocess :: managed_shared_memory將給定的數據結構存儲在共享內存中的映射中。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 

這是一個如何使用它的例子。

#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; 
} 

這裏是一個堆棧跟蹤:

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()

+0

您可能想要顯示使用此標頭的最小程序並顯示崩潰。另外,讓我們知道它是否僅與程序的單個實例崩潰,或者實際上是否必須主動共享以共享崩潰?最後,平臺細節和堆棧跟蹤可能會很有用。 –

+0

@Michael Burr:這是用VS2010編譯的Windows 7 – andre

+0

我得到它的工作。問題是行'static const char * memory(){return std :: string(「simple_memory_page」)。c_str();}'必須改爲'static const char * memory(){return「simple_memory_page」; '誰能解釋爲什麼? – andre

回答

5

它看起來像你將std::string類型放在共享內存中,這將無法工作,因爲它會爲自己分配非共享內存。您應該使用boost::interprocess::basic_string類型,而不是<boost/interprocess/containers/string.hpp>。有一個將字符串放入地圖here的示例。


要回答你上面的註釋問,該字符串被破壞後string::c_str()返回的值變爲無效。這意味着訪問由memory()返回的指針將導致未定義的行爲。

+0

我在共享內存中使用''映射'而不是字符串。目前它對我來說工作得很好。 – andre

+0

@ahenderson不是一個字符串?您正在使用'std :: string'作爲地圖的關鍵字。僅僅因爲它在一個特定的測試中工作並不意味着它總是會的。 – interjay

+0

感謝您的回答,我感謝您花時間回答。我只有一個問題,假設我不能將std :: string作爲maps鍵。如果是這種情況,則映射的值也必須是進程間容器兼容類型。這對於地圖來說似乎非常有限。我懷疑通過創建一個分配器類型,我可以在地圖中使用它。我將不得不做更多的研究來理解這個問題。 – andre

1

要添加到interjay寫入的關於string :: c_str()的內容,返回的值不保證在第一個非常量成員調用字符串對象後有效。因此,對string :: resize的後續調用可能會使由string :: c_str()返回的值無效。

相關問題