2017-04-11 10 views
0

さまざまなプロセスが管理対象共有メモリに格納されたデータにアクセスできるプログラムを作成しようとしています。私は仕事を達成するためにブーストを利用しています。私は3つのファイル、shared_memory.h、shared_memory.cc、main.ccを持っています。ブースト管理された共有メモリsegfault

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

私はサーバモードとして、プログラムを実行すると、すべてが正常に動作します。しかし、実行中のサーバー・プロセスがあり、追加のクライアント・プロセスを作成すると、共有メモリー内で構築されたオブジェクトを見つけようとするときにsegfaultsが発生します。具体的には、SharedItn::Read関数内のtransTmp = tmp->at(i).Copy(true);というコードでsegfaultが発生します。

クライアントから呼び出されたfindメソッドが正しく機能していないことを推測します。しかし、私は問題が何であるか把握することはできません。どんな助けでも大歓迎です。

+0

ご覧のとおり、誰もこの大量のコードを掘り下げようとしていませんでした。次回MCVEで試してみてください。 –

+0

@AlBundyトラフィックの少ないタグでは7時間と非常に短いです。コードはSSCCE – sehe

答えて

1

TransducerがPODでない限り、これは問題の可能性があります。

fst::Vector<>は、共有メモリ・セグメントの外側に割り当てる場合、それはdifferenプロセスで範囲外取り組みます。

+0

として知られています。素早くGoogle検索すると、[VectorFst]の[link](http://www.openfst.org/doxygen/fst/html/vector-fst_8h_source.html)が表示されます。これがOPが使用しているライブラリであると仮定すると、PODタイプではありません**。 –

+0

@ NathanErnstが同意した。私はそれをインストールした。私が他の多くの基本コードの問題を見たときに失われた興味。本質的な問題を指摘することを決めた – sehe

+0

あなたはすでに私のupvoteを持っています。あなたが指摘した問題は間違いなく問題です(唯一の問題ではないかもしれません)。動的に割り当てられたメモリへのポインタを含む非PODは、共有メモリではうまく動作しません。 –

関連する問題