2017-04-11 131 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绝对不会与共享内存兼容。 –