【问题标题】:boost managed shared memory segfault提升托管共享内存段错误
【发布时间】:2017-04-11 00:44:05
【问题描述】:

我正在尝试创建一个程序,其中各种进程可以访问存储在托管共享内存中的数据。我正在利用 boost 来完成任务。我有三个文件,shared_memory.h、shared_memory.cc 和 main.cc。

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-&gt;at(i).Copy(true);SharedItn::Read 函数中。

我的最佳猜测是客户端调用的 find 方法无法正常运行。但是,我无法弄清楚问题所在。任何帮助将不胜感激。

【问题讨论】:

  • 如您所见,没有人愿意挖掘大量代码。下次使用 MCVE 试试。
  • @AlBundy 7 小时对于低流量标签来说非常短。代码就是所谓的 SSCCE

标签: c++ boost shared-memory


【解决方案1】:

除非Transducer 是 POD,否则这很可能是您的问题。

如果fst::Vector&lt;&gt; 在共享内存段之外分配,它将在不同的进程中越界。

【讨论】:

  • 一个快速的谷歌搜索出现了这个linkVectorFst。假设这是 OP 正在使用的库,它绝对不是 POD 类型。
  • @NathanErnst 同意了。我已经安装了。当我看到许多其他基本代码问题时失去了兴趣。决定只指出本质问题
  • 你已经得到了我的支持。您指出的问题绝对是一个问题(可能不是唯一的问题)。包含指向动态分配内存的指针的非 POD 肯定不能很好地与共享内存配合使用。
猜你喜欢
  • 2012-10-19
  • 2021-12-12
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多