2017-04-11 120 views
0

我想創建一個程序,其中各個進程可以訪問存儲在管理共享內存中的數據。我正在利用助推來完成任務。我有三個文件,shared_memory.h,shared_memory.cc和main.cc.boost管理共享內存段錯誤

shared_memory.h

#ifndef __SHARED_ITN__ 
#define __SHARED_ITN__ 

#include <fst/fstlib.h> 

#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/containers/vector.hpp> 


enum TokenType { SYMBOL = 1, BYTE = 2, UTF8 = 3 }; 
using namespace boost::interprocess; 

typedef fst::VectorFst<fst::StdArc> Transducer; 
typedef allocator<Transducer, managed_shared_memory::segment_manager> shmMyFstAllocator; 
typedef boost::interprocess::vector<Transducer, shmMyFstAllocator> shmMyFst; 

class SharedItn { 

    public: 
     SharedItn(); 
     SharedItn(std::vector<string> model_path); 
     bool Read(std::vector<string> model_path, string input_str, string &output_str); 
     void Remove(); 
     virtual ~SharedItn(); 

    private: 
     static const string SHM_OBJ_IDENTIFIER; 
     static const int SHM_OBJ_SIZE; 
     shmMyFst* myFstPtr; 
}; 

#endif 

相應的C++代碼,shared_memory.cc是:

shared_memory.cc

#include "shared_memory.h" 
#include <cstdlib> 
#include <cstring> 
#include <vector> 

using namespace fst; 

typedef VectorFst<StdArc> Transducer; 
typedef StringCompiler<StdArc> Compiler; 

const string SharedItn::SHM_OBJ_IDENTIFIER = "SHARED_ITN_MODULES"; 
const int SharedItn::SHM_OBJ_SIZE = 104857600; 

SharedItn::SharedItn() { 
} 

SharedItn::SharedItn(std::vector<string> model_path) { 
try { 
    // Create managed shared memory object 
    shared_memory_object::remove(SHM_OBJ_IDENTIFIER.c_str()); 
    managed_shared_memory segment(create_only, SHM_OBJ_IDENTIFIER.c_str(), SHM_OBJ_SIZE); 

    // Construct fst model within the shared memory object 
    shmMyFstAllocator alloc_inst(segment.get_segment_manager()); 
    myFstPtr = segment.construct<shmMyFst>(model_path[0].c_str())(alloc_inst); 

    // Insert the loaded fst model into shared memory 
    Transducer* tmp_model_fst = Transducer::Read(model_path[0]);    
    myFstPtr->push_back(*tmp_model_fst); 

} catch (interprocess_exception& e) { 
     std::cout << e.what() << std::endl; 
} 
} 

SharedItn::~SharedItn() {} 

bool SharedItn::Read(std::vector<string> model_path, string input_str, string& output_str) { 

Transducer* transTmp; 
shmMyFst* tmp; 

try { 
    managed_shared_memory segment(open_only, SHM_OBJ_IDENTIFIER.c_str()); 
    tmp = segment.find<shmMyFst>(model_path[0].c_str()).first; 
    for(int i = 0; i < tmp->size(); i++) 
     transTmp = tmp->at(i).Copy(true); 

} catch (interprocess_exception& e) { 
     std::cout << e.what() << std::endl; 
     return false; 
} 

return true; 
} 

void SharedItn::Remove() { 
try { 
    shared_memory_object::remove(SHM_OBJ_IDENTIFIER.c_str()); 
} catch(interprocess_exception& e) { 
    std::cout << e.what() << std::endl; 
} 
} 

最後在其中創建服務器/客戶端進程的main.cc文件。

main.cc

#include "shared_memory.h" 

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

if(argc != 2) { 
    std::cout << "Must provide either 'server' or 'client' as input." << std::endl; 
    return -1; 
} else { 
     std::vector<string> file_path; 
     std::string file = "rule_PRE_PROC.fst"; 
     file_path.push_back(file); 

     string input_str = ""; 
     string result_str; 

     if(std::string(argv[1]) == "server") { 
      SharedItn loader(file_path); 

      while(1) { 
       std::cout << "Input test string: " << std::endl; 
       getline(std::cin, input_str); 
       if(input_str.compare("quit") == 0) { 
        loader.Remove(); 
        std::cout << "Terminating." << std::endl; 
        break; 
       } 
       loader.Read(file_path, input_str, result_str); 
       std::cout << "RESULT: " << result_str << std::endl; 
      } 
     } else if(std::string(argv[1]) == "client") { 
       SharedItn loader; 

       while(1) { 
        std::cout << "Input test string: " << std::endl; 
        getline(std::cin, input_str); 
        if(input_str.compare("quit") == 0) { 
         loader.Remove(); 
         std::cout << "Terminating." << std::endl; 
         break; 
        } 
        loader.Read(file_path, input_str, result_str); 
        std::cout << "RESULT: " << result_str << std::endl; 
       } 
     } 
} 
} 

當我運行程序服務器模式,一切工作正常。但是,當我有一個正在運行的服務器進程並創建一個額外的客戶端進程時,它會在嘗試在共享內存中查找構造的對象時發生段錯誤。更具體地說,段錯誤發生在以下代碼中:transTmp = tmp->at(i).Copy(true);SharedItn::Read函數內。

我最好的猜測是客戶端調用的find方法無法正常工作。但是,我無法弄清楚問題所在。任何幫助將不勝感激。

+0

正如你所看到的,沒有人願意挖掘這些大量的代碼。下次嘗試使用MCVE。 –

+0

@AlBundy對於低流量標籤,7小時是非常短的。代碼是所謂的SSCCE – sehe

回答

1

除非Transducer是POD,這可能是您的問題。

如果fst::Vector<>在共享內存段外分配,它將尋址在不同過程中的界限。

+0

快速谷歌搜索爲'VectorFst'出現了這個[link](http://www.openfst.org/doxygen/fst/html/vector-fst_8h_source.html)。假設這是OP正在使用的庫,那肯定是不是** POD類型。 –

+0

@NathanErnst同意了。我安裝了它。當我看到一些其他基本代碼問題時,失去興趣。決定只是指出基本問題 – sehe

+0

你已經得到我的upvote。你指出的問題肯定是一個問題(可能不是唯一的問題)。包含指向動態分配內存指針的非POD絕對不會與共享內存兼容。 –