如何正确地将带有 vtable 的 class 实例写入和读取到 QSharedMemory 中?
How to properly write and read class instance with vtable into the QSharedMemory?
我有一个从接口派生的 class
class Interface {
public:
virtual void foo() = 0;
};
class Implementer : public Interface {
public:
void foo() override { std::cout << "Hello world" << std::endl; }
private:
int __some_int_member;
};
现在我想写一个程序,它将在所有应用程序实例中获得相同的Implementer
实例class。我遵循了建议的示例 here(第二个),但在该示例中,仅使用了一个字节。
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
Implementer *impl = nullptr;
QSystemSemaphore accessor("app_accessor", 1);
accessor.acquire();
#ifndef QT_OS_WIN
QSharedMemory mem_fix("my_class");
if(mem_fix.attach())
{
mem_fix.detach();
}
#endif
QSharedMemory mem("my_class");
if(!mem.attach())
{
mem.create(sizeof(Implementer));
new(mem.data()) Implementer();
}
impl = (Implementer*)mem.data();
accessor.release();
impl->foo();
return app.exec();
}
第一个实例运行良好。但是它在 impl->foo()
.
线上的第二个崩溃了
我认为原因是从 void*
到 Implementer*
的演员阵容不好。但我不知道如何正确地做到这一点。
有什么建议吗?
编辑
我意识到,由 分段错误 引起的崩溃是继承的结果,因为没有基础 class 一切正常。
编辑 2
经过一些调试、内存转储和一些评论后,我意识到,问题是在运行时程序的第一个实例在其堆栈中创建 vtable
并将 vptr
放入它 vtable
。第二个实例得到相同的vptr
,不幸的是,它指向一些随机内存(可能已分配或未分配)。
具有虚函数的基础 class 需要 vtable
。 The memory location of the vtable or even the existence of it is implementation-dependent,因此当您尝试通过 vtable
.
访问函数时会出现异常
你能做的就是把数据和逻辑分开。定义一个只有数据的新 class,共享它并在其上应用一些功能。
但是,由于您打算将 QMap
作为数据共享,因此您似乎还会遇到更多问题。它可能将其数据存储在堆上并且不提供内存分配器接口(至少我看不到)。这意味着您将无法控制它在何处分配数据。如果你确定你需要一个地图结构,你可以使用 std::map
并为使用你创建的共享内存的地图提供你自己的内存分配器。我刚刚在 google 中写了 c++ std map custom memory allocator
,它显示了一些解决方案。 SO 中还有 this 个问题可能对您有所帮助。
我有一个从接口派生的 class
class Interface {
public:
virtual void foo() = 0;
};
class Implementer : public Interface {
public:
void foo() override { std::cout << "Hello world" << std::endl; }
private:
int __some_int_member;
};
现在我想写一个程序,它将在所有应用程序实例中获得相同的Implementer
实例class。我遵循了建议的示例 here(第二个),但在该示例中,仅使用了一个字节。
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
Implementer *impl = nullptr;
QSystemSemaphore accessor("app_accessor", 1);
accessor.acquire();
#ifndef QT_OS_WIN
QSharedMemory mem_fix("my_class");
if(mem_fix.attach())
{
mem_fix.detach();
}
#endif
QSharedMemory mem("my_class");
if(!mem.attach())
{
mem.create(sizeof(Implementer));
new(mem.data()) Implementer();
}
impl = (Implementer*)mem.data();
accessor.release();
impl->foo();
return app.exec();
}
第一个实例运行良好。但是它在 impl->foo()
.
我认为原因是从 void*
到 Implementer*
的演员阵容不好。但我不知道如何正确地做到这一点。
有什么建议吗?
编辑
我意识到,由 分段错误 引起的崩溃是继承的结果,因为没有基础 class 一切正常。
编辑 2
经过一些调试、内存转储和一些评论后,我意识到,问题是在运行时程序的第一个实例在其堆栈中创建 vtable
并将 vptr
放入它 vtable
。第二个实例得到相同的vptr
,不幸的是,它指向一些随机内存(可能已分配或未分配)。
具有虚函数的基础 class 需要 vtable
。 The memory location of the vtable or even the existence of it is implementation-dependent,因此当您尝试通过 vtable
.
你能做的就是把数据和逻辑分开。定义一个只有数据的新 class,共享它并在其上应用一些功能。
但是,由于您打算将 QMap
作为数据共享,因此您似乎还会遇到更多问题。它可能将其数据存储在堆上并且不提供内存分配器接口(至少我看不到)。这意味着您将无法控制它在何处分配数据。如果你确定你需要一个地图结构,你可以使用 std::map
并为使用你创建的共享内存的地图提供你自己的内存分配器。我刚刚在 google 中写了 c++ std map custom memory allocator
,它显示了一些解决方案。 SO 中还有 this 个问题可能对您有所帮助。