c++ - 在类对象段错误中使用 boost::interprocess ,为什么?

标签 c++ class boost segmentation-fault boost-interprocess

我正在尝试让一些代码工作,使用一个类来设置和管理共享内存,并从我的主程序中调用该类的对象。所有代码直接在我的 main() 中时都可以工作,但是当我在类中设置它并实例化该类的对象时,我会遇到段错误。

我不知道为什么或如何解决它?

这里的第一个示例显示了在我的 main() 函数中没有问题的示例:

#include <boost/interprocess/managed_shared_memory.hpp>
using namespace boost::interprocess;

typedef struct teststruct {
    int     testint=9;
};

typedef std::pair<teststruct, int> memsh_teststruct;

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


    printf("inMain0\n");


    struct shm_remove
    {
        shm_remove() { shared_memory_object::remove("testShare"); }
        ~shm_remove(){ shared_memory_object::remove("testShare"); }
    } remover;

    //Construct managed shared memory
    managed_shared_memory segment(create_only, "testShare", 65536);


    teststruct myTeststruct;
    memsh_teststruct *inst_teststruct;

    inst_teststruct = segment.construct<memsh_teststruct>
        ("name_myTeststruct") 
        (myTeststruct, 0); 

    printf("construct_ptr: %p \n", &inst_teststruct->first);

    inst_teststruct->first.testint = 1234;

    printf("construct_val: %d\n", inst_teststruct->first.testint);




    int mainInt;

    printf("inMain1\n");

    mainInt = inst_teststruct->first.testint;

    printf("mainInt: %d\n", mainInt);

    printf("inMain2\n");
}

输出看起来不错,如下所示:

construct_ptr: 0x7f0d41834118 
construct_val: 1234
inMain0
inMain1
mainInt: 1234
inMain2

这是第二个示例,它设置完全相同的共享内存,但使用类。

#include <boost/interprocess/managed_shared_memory.hpp>
using namespace boost::interprocess;

typedef struct teststruct {
    int     testint=9;
};


typedef std::pair<teststruct, int> memsh_teststruct;

class testclass{
    public:
        testclass();
        bool something(int in);

        teststruct myTeststruct;
        memsh_teststruct *inst_teststruct;
};



testclass::testclass() 
{
    struct shm_remove
    {
        shm_remove() { shared_memory_object::remove("testShare"); }
        ~shm_remove(){ shared_memory_object::remove("testShare"); }
    } remover;

    //Construct managed shared memory
    managed_shared_memory segment(create_only, "testShare", 65536);

    inst_teststruct = segment.construct<memsh_teststruct>
        ("name_myTeststruct") 
        (myTeststruct, 0); 

    printf("construct_ptr: %p \n", &inst_teststruct->first);

    inst_teststruct->first.testint = 1234;

    printf("construct_val: %d\n", inst_teststruct->first.testint);
}



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

    printf("inMain0\n");

    int mainInt;
    testclass testclassObj;

    printf("inMain1\n");

    mainInt = testclassObj.inst_teststruct->first.testint;

    printf("mainInt: %d\n", mainInt);

    printf("inMain2\n");
}

但是第二个示例出现段错误,这是输出:

inMain0
construct_ptr: 0x7fa222d37118 
construct_val: 1234
inMain1
Segmentation fault (core dumped)

...那么为什么调用

mainInt = testclassObj.inst_teststruct->first.testint;

来自 main() 导致段错误?

我还尝试了一些其他变体,例如在类中定义其他函数来与共享内存变量交互,并且它也会出现段错误。

如果我必须猜测发生了什么,我感觉共享内存正在关闭或者在我预期之前关闭,可能是在退出 testclass() 构造函数之后。但是,我不知道避免这种情况的正确方法,因此当整个 testclassObj 对象被清理时,从 main() 返回时共享内存会被关闭。

另一方面,也许我完全错了?

谢谢,

编辑: 编辑2:最后一次编辑被删除,我的错误是无关紧要的,并且由于我在肖恩的回答中对评论线程做了一些愚蠢的事情。

最佳答案

您的猜测是完全正确的,共享内存会在您预期之前关闭。

managed_shared_memory build 于testclass::testclass并在构造函数末尾超出范围,关闭共享内存,但留下 inst_teststruct指向共享内存曾经所在的位置。

您必须保留 segment只要有指针就可以。最简单的方法可能是举起 segment成为testclass的类(class)成员像这样:

class testclass {
public:
    testclass();

    managed_shared_memory segment;
    teststruct myTeststruct;
    memsh_teststruct *inst_teststruct;
};

testclass::testclass()
    : segment(create_only, "testShare", 65536) //< Construct managed shared memory
{
    struct shm_remove {
        shm_remove() { shared_memory_object::remove("testShare"); }
        ~shm_remove() { shared_memory_object::remove("testShare"); }
    } remover;

    inst_teststruct = segment.construct<memsh_teststruct>
        ("name_myTeststruct")
        (myTeststruct, 0);

    printf("construct_ptr: %p \n", &inst_teststruct->first);

    inst_teststruct->first.testint = 1234;

    printf("construct_val: %d\n", inst_teststruct->first.testint);
}

但是,您必须考虑如何最好地管理共享内存的生命周期,特别是考虑到还会涉及另一个进程。

关于c++ - 在类对象段错误中使用 boost::interprocess ,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37631469/

相关文章:

c++ - 三个数字的最大成对递减次数

c++ - 为什么 test2 + test3 的运算符 << 不能重载?

c++ - 实现二进制搜索树时对类的怀疑

c++ - 处理程序抛出异常后是否需要重置 asio::io_service ?

c++ - 在 Managed_shared_memory 中 boost 进程间互斥

c++ - 有没有办法将源代码格式化为每行只包含一条语句?

c++ - 使用构造函数代替或类型转换运算符

c++ - 动态分配数据类型 C++

c++ - 我对 boost::mpi::request 缺少什么?测试似乎改变了状态

C++ VS 工具集 141 - 142 转换的差异