C++ 使用相同proto的多个共享对象导致错误:数据库中已存在文件

C++ 使用相同proto的多个共享对象导致错误:数据库中已存在文件,c++,dlopen,protocol-buffers,C++,Dlopen,Protocol Buffers,与protobuf3相关的错误 我有一个项目,有一个C++可执行内核,几个共享对象(.SO,.DLL)称为插件。当核心启动时,它将加载那些带有dlopen的插件。核心和插件使用protobuf作为通信协议,因此它们必须将生成的.pb.cc和.ph.h文件编译成二进制文件,以获得序列化器/反序列化器的副本。和libprotobuf.so链接到核心和插件。当我启动core时,它会出错:数据库中已经存在文件,数据库中也存在相同的错误 我正在使用protobuf-3 beta2和Ubuntu 14.04

与protobuf3相关的错误

我有一个项目,有一个C++可执行内核,几个共享对象(.SO,.DLL)称为插件。当核心启动时,它将加载那些带有dlopen的插件。核心和插件使用protobuf作为通信协议,因此它们必须将生成的

.pb.cc
.ph.h
文件编译成二进制文件,以获得序列化器/反序列化器的副本。和
libprotobuf.so
链接到核心和插件。当我启动core时,它会出错:数据库中已经存在文件,数据库中也存在相同的错误

我正在使用protobuf-3 beta2和Ubuntu 14.04。此错误仅在Linux上发生。该程序在Windows和OSX上运行良好

我还尝试了另一种方法,将所有生成的protobuf文件编译成一个动态库(
protobuf.so
),然后将核心和插件链接到
protobuf.so
)和
libprotobuf.so
。这个很好用。当然,因为在这个错误已经被修复。但是,当我将
协议.so
更改为
协议.a
时,它再次失败。我认为它与单独编译生成的
.pb.cc
是一样的

我不想编译一个
协议。所以
,因为当我添加越来越多的插件时,扩展通信协议对我来说很不方便。我认为将生成的
.pb.cc
编译成插件的二进制文件更好(这在windows和OSX上运行得很好)


如果您有相同
.pb.cc
文件的多个编译副本共享一个
libprotobuf.so
副本,则会出现问题。有两种方法可以避免这种情况:

  • 您已经找到的方法是:将
    .pb.cc
    文件分解到共享库中
  • 将libprotobuf的单独副本链接到每个插件中。您需要对此库使用静态链接,即使用
    libprotobuf.a
    而不是
    libprotobuf.so
    。请注意,使用此选项时,在插件和基础应用程序之间传递指向protobuf类的指针是不安全的,因为它们使用protobuf库的单独副本,这可能导致崩溃。您将不得不以字节blob的形式传递序列化消息。幸运的是,这就是protobuf的全部要点

  • 我通过向dlopen添加RTLD_GLOBAL解决了这个问题,dlopen考虑了现有的已知符号。

    错误是什么?复制粘贴-您至少可以在文本中添加指向所指问题的链接!抱歉,我忘了放置github链接。现在,我添加了#863和#1062的链接。谢谢~嗨,谢谢你的建议。我已经试过方法2,但仍然有同样的错误。你对此有什么看法吗?@piaoxu如果你得到同样的错误,那么不知何故你的插件仍然共享同一份libprotobuf。你得弄清楚原因。对不起,我没有任何猜测/@KentonVarda不仅必须将
    libprotobuf.a
    链接到每个插件中,而且(由于通常的ELF符号可见性规则),必须隐藏插件中的所有
    libprotobuf.a
    符号(使用
    -fvisibility=hidden
    ,或使用链接器版本脚本)。再多谈一点。@KentonVarda,是的,你说得对。他们仍然不知何故共享同一份libprotobuf。谢谢:)我不明白。如果我只共享一个指针而不共享一个副本,那么在创建这个插件的插件中不会调用所有操作吗???为什么这样不安全?