我创建了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;从测试方法,一切正常 - 出现消息框。是否存在我无法修改映射内存中对象的限制,或者这是以其他方式完成的吗?
答案 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并删除静态修改器,可以避免所有这些陷阱。