Several shared object using same proto leading the the error: file already exists in database

Several shared object using same proto leading the the error: file already exists in database

与 protobuf3 有关的错误

我有一个项目,它有一个 C++ 可执行核心和几个称为插件的共享对象(.so、.dll)。当核心启动时,它将使用 dlopen 加载这些插件。核心和插件使用 protobuf 作为通信协议,因此它们必须将生成的 .pb.cc.ph.h 文件编译到它们的二进制文件中以获得 serializer/deserializer 的副本。 libprotobuf.so link 到核心和插件。当我启动核心时,它崩溃并出现错误:文件已存在于数据库中,#863

中也有同样的错误

我正在使用 protobuf-3 beta2 和 Ubuntu 14.04。此错误仅发生在 Linux。该程序在 Windows 和 OS X.

上运行良好

我还尝试了另一种方法,将所有生成的 protobuf 文件编译成动态库 (protocol.so),然后核心和插件被 linked 为 protocol.solibprotobuf.so。这很好用。当然,因为在 #1062 中,错误已得到修复。但是当我把protocol.so改成protocol.a的时候,又失败了。我认为它与单独编译生成的.pb.cc相同。

不想编一个protocol.so,因为插件越来越多,不方便扩展通讯协议。我认为将生成的 .pb.cc 编译成插件的二进制文件更好(这在 windows 和 OS X 上运行良好)。

如有任何修复此错误的建议,我们将不胜感激。

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

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

我能够通过将 RTLD_GLOBAL 添加到 dlopen 来解决这个问题,它考虑了现有的已知符号。

我通过向 dlopen 添加 RTLD_DEEPBIND 解决了这个问题。

就我而言,当我尝试 运行 Gazebo 中的插件与教程项目时,出现“文件已存在于数据库中”错误。

我能够通过将 .so 文件复制到我尝试启动程序的本地目录而不是将 GAZEBO_PLUGIN_PATH 变量设置到构建目录来解决这个问题。

我希望类似的解决方案在遇到 Gazebo 插件以外的问题时对其他人有用。 (也许一般的解决方法是将你的.so文件复制到本地而不是build)