如何正确地将带有 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 需要 vtableThe 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 个问题可能对您有所帮助。