0

我有一个从接口派生的类

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在所有应用程序实例中获取相同的类实例。我按照此处建议的示例(第二个)进行操作,但在该示例中,仅使用了一个字节。

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*. 但我不知道如何正确地做到这一点。

有什么建议么?

编辑

我意识到,由分段错误引起的崩溃是继承的结果,因为没有基类,一切正常。

编辑 2

经过一些调试、内存转储和一些注释后,我意识到问题在于,在运行时程序的第一个实例vtable在其堆栈中创建了 并将其vptr放入vtable. 第二个实例得到相同的vptr结果,不幸的是,它指向一些随机内存(可能已分配或未分配)。

4

1 回答 1

1

具有虚函数的基类需要一个vtable. vtable 的内存位置甚至它的存在是依赖于实现的,因此当您尝试通过 访问函数时会出现异常vtable

您可以做的是将数据和逻辑分开。定义一个只有数据的新类,共享它并在其上应用一些功能。

QMap但是,由于您计划作为数据共享,因此您似乎会遇到更多问题。它可能将其数据存储在堆上并且不提供内存分配器接口(至少我看不到)。这意味着您将无法控制它分配数据的位置。如果您确定需要一个映射结构,您可以使用std::map并提供您自己的内存分配器给使用您创建的共享内存的映射。我刚刚c++ std map custom memory allocator在谷歌上写过,它显示了一些解决方案。SO中也有这个问题可以帮助你。

于 2019-08-01T05:55:39.130 回答