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

时间:2016-06-04 14:41:20

标签: 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");
}

但是第二个例子是segfaults,这是输出:

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

...那么为什么要调用

mainInt = testclassObj.inst_teststruct->first.testint;
来自main()的

会导致段错误吗?

我还尝试了其他一些变体,例如在我的类中定义其他函数以与共享内存变量进行交互,还有段错误。

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

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

谢谢, 乙

编辑: EDIT2:删除了最后一个编辑,我的错误无关紧要,并且由于我在回答中与Sean的评论主题做了一些愚蠢的事。

1 个答案:

答案 0 :(得分:1)

你猜测共享内存在你预期之前就已经关闭了,这是完全正确的。

managed_shared_memorytestclass::testclass中构造,并且在构造函数结束时超出范围,关闭共享内存,但是inst_teststruct指向共享内存的位置

只要有指针,就必须保持segment左右。最简单的方法是将segment提升为testclass的类成员,如下所示:

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

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