在DLL中提升共享内存对象

时间:2014-08-21 21:32:42

标签: c++ memory boost dll shared

我创建了dll并实现了每个连接进程都可以使用的共享内存。我的问题是,我无法改变存储在内存中的对象中的任何内容。

我的班级:

class MyClass
{
public:
    MyClass();
    void test();
    int counter;
};

void MyClass::test() {
    MessageBoxA(NULL, "test", "test", 0x0000000L);
    counter++;
}

在stdafx.h中我有:

static offset_ptr<MyClass> offset_mt;
static managed_shared_memory *memSegment;

我初始化共享内存和指针:

memSegment = new managed_shared_memory(create_only, SHARED_MEMORY_NAME, 4096);
offset_mt = memSegment->construct<MyClass>("MyClass myClass")();

然后在导出的函数中调用

offset_mt.get()->test();

我使用JNA从Java调用它,结果是内存错误(内存访问无效)。但是,如果我删除&#39; counter ++&#39;从测试方法,一切正常 - 出现消息框。是否存在我无法修改映射内存中对象的限制,或者这是以其他方式完成的吗?

2 个答案:

答案 0 :(得分:0)

好吧,我通过将变量移动到stdafx.cpp来解决这个问题:

offset_ptr<MyClass> offset_mt;
managed_shared_memory *memSegment;

在stdafx.h中将它们作为extern:

extern offset_ptr<MyClass> offset_mt;
extern managed_shared_memory *memSegment;

现在它运行良好,但我已经意外地做了这种事情,我不太清楚为什么这样做,以前的方式没有。如果有人能向我解释这一点,那就太好了。

答案 1 :(得分:0)

当你说

static offset_ptr<MyClass> offset_mt;

编译器必须做一些事情。其中一个是为变量分配空间(参见where static variables are stored)。另一个是调用任何重要的构造函数。在main()(或dllmain)运行之前,最后一部分由CRT完成。实际上,在调用[dll] main()之前,CRT会替换您的入口点并初始化静态。

当你在标题中说,编译器为每个包含标题的编译单元中的变量分配空间。

当你在stdafx.h中说这意味着每个cpp文件。通常这会导致链接器错误,但有时它会滑过(一种方法是使用匿名命名空间)并导致不同的cpp文件看到变量的不同副本。所以,如果你在一个cpp中初始化,而在另一个cpp中使用它,你会爆炸。

当您以有趣的方式导入dll时,有时导入代码根本不会调用入口点 - 这会杀死大多数CRT工具并导致您自己的静态未初始化。不知道JNA,但是.Net的一些旧版本存在这个问题。

还有static initialization fiasco,但这可能不会影响您的具体情况。

通过将定义移动到cpp并删除静态修改器,可以避免所有这些陷阱。