【问题标题】:Conflict Protobuf version when using Opencv and Tensorflow c++使用 Opencv 和 Tensorflow c++ 时的 Protobuf 版本冲突
【发布时间】:2017-06-17 06:44:49
【问题描述】:

我目前正在尝试在非 bazel 项目中使用 Tensorflow 的共享库,因此我使用 bazel 从 tensorflow 创建了一个 .so 文件。

但是当我启动一个同时使用 Opencv 和 Tensorflow 的 c++ 程序时,它使我出现以下错误:

[libprotobuf FATAL external/protobuf/src/google/protobuf/stubs/common.cc:78] 该程序是针对 Protocol Buffer 运行时库的 2.6.1 版本编译的,与安装的版本(3.1 .0)。联系程序作者获取更新。如果您自己编译程序,请确保您的标头来自与链接时库相同版本的 Protocol Buffers。 (“/build/mir-pkdHET/mir-0.21.0+16.04.20160330/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc”中的版本验证失败。) 在抛出 'google::protobuf::FatalException' 的实例后调用终止

what():该程序是针对 Protocol Buffer 运行时库的 2.6.1 版本编译的,该版本与已安装的版本 (3.1.0) 不兼容。联系程序作者获取更新。如果您自己编译程序,请确保您的标头来自与链接时库相同版本的 Protocol Buffers。 (“/build/mir-pkdHET/mir-0.21.0+16.04.20160330/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc”中的版本验证失败。) 放弃(核心转储)

你能帮帮我吗?

谢谢

【问题讨论】:

  • 那条消息到底有什么不清楚的地方?
  • 问题是即使我尝试安装 3.1.0 版本我仍然得到同样的错误
  • 此程序是针对 Protocol Buffer 运行时库的 2.6.1 版本编译的,该版本与已安装的版本 (3.1.0) 不兼容。请联系程序作者以获取更新。您是否使用 protobuf 3.1.0 重新编译了库??
  • 是的,我做到了,但我仍然遇到同样的错误
  • 我遇到了类似的问题。我必须将 protobuf 静态链接到我的一个共享库中。如果您nm -D 任一共享库,您将看到 Protobuf 的冲突符号。祝你好运!这对我来说超级痛苦

标签: c++ opencv tensorflow protocol-buffers


【解决方案1】:

该错误表明程序是使用 protobuf 2.6.1 中的标头(.h 文件)编译的。这些标头通常位于 /usr/include/google/protobuf/usr/local/include/google/protobuf 中,但根据您的操作系统和程序的构建方式,它们可能位于其他位置。您需要将这些头文件更新到版本 3.1.0 并重新编译程序。

【讨论】:

  • 我在/usr/local/include/google/protobuf中有正确的标题.....我发现一些.so opencv文件依赖于libprotobuf-lite.so.9(在/usr/lib/x86_64-linux-gnu/中)。
  • 嗯,消息说程序是用旧的 protobuf 头编译的。我是写该错误消息的人,我可以向您保证它没有错。您必须弄清楚程序如何以旧标题结束。另一种可能性是程序的构建系统将其自己的标头副本(版本错误)下载到本地构建中,而不是使用系统安装的副本。但我不知道。这里有无限可能。
  • 你是对的,这里有无限可能。当我安装 Opencv 时,我使用 GTK3 进行安装(但问题是 gtk3 取决于 protobuf 2.6.1),这就是为什么我在同一个 cpp 文件中使用 Opencv 和 tensorflow 时看到此错误的原因。为了解决我的问题,我用 GTK2 安装了 opencv,它不依赖于 protobuf 2.6.1。感谢@Kenton Varda 的帮助。
  • 啊哈哈,所以实际上你所依赖的库——你没有重新编译——是使用旧头文件构建的。有道理。
  • @Bersan 需要明确的是,这不是 protobuf 特有的问题。 Linux 上动态链接的本质使得将同一个库的多个版本链接到同一个进程是不安全的,而 C++ 的本质使得新版本的 C++ 库提供向后兼容的 ABI 几乎是不可行的。也就是说,未来的 protobuf 版本或许应该考虑使用 C++11 内联命名空间来解决这个问题;该功能在 protobuf 首次发布时不可用。
【解决方案2】:

这确实是一个相当严重的问题!我收到与您类似的以下错误:

$./ceres_single_test 
[libprotobuf FATAL google/protobuf/stubs/common.cc:78] This program was compiled against version 2.6.1 of the Protocol Buffer runtime library, which is not compatible with the installed version (3.1.0).  Contact the program author for an update.  If you compiled the program yourself, make sure that your headers are from the same version of Protocol Buffers as your link-time library.  (Version verification failed in "/build/mir-pkdHET/mir-0.21.0+16.04.20160330/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc".)
terminate called after throwing an instance of 'google::protobuf::FatalException'
Aborted

我的解决方法:

cd /usr/lib/x86_64-linux-gnu
sudo mkdir BACKUP
sudo mv libmirprotobuf.so* ./BACKUP/

现在,正在测试的可执行文件可以运行了,很酷。然而,不酷的是,如果不从将 BACKUP 路径添加到 LD_LIBRARY_PATH 的 shell 中运行,gedit 之类的东西就不再工作了 :-(
希望那里有更好的解决方案?

【讨论】:

  • 如果您仍然遇到问题,我已经找到了一个解决方案,我将其发布为答案。
  • 我很困惑,为什么会这样?你移动了 protobuf 库,现在找不到了?因此,它必须使用安装在另一个路径上的库,对吧?如果是这种情况,你可以试试invoking the executable while specifying the path of the correct protobuf
【解决方案3】:

您应该使用链接器脚本重新构建 TensorFlow,以避免在 Bazel 创建的共享库中使第三方符号成为全局符号。这就是用于 TensorFlow 的 Android Java/JNI 库能够与设备上预安装的 protobuf 库共存的方式(查看tensorflow/contrib/android 中的构建规则以获取工作示例)

这是我从 Android 库改编的 BUILD 文件来执行此操作:

package(default_visibility = ["//visibility:public"])

licenses(["notice"])  # Apache 2.0

exports_files(["LICENSE"])

load(
    "//tensorflow:tensorflow.bzl",
    "tf_copts",
    "if_android",
)

exports_files([
    "version_script.lds",
])

# Build the native .so.
# bazel build //tensorflow/contrib/android_ndk:libtensorflow_cc_inference.so \
#   --crosstool_top=//external:android/crosstool \
#   --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
#   --cpu=armeabi-v7a
LINKER_SCRIPT = "//tensorflow/contrib/android:version_script.lds"

cc_binary(
    name = "libtensorflow_cc_inference.so",
    srcs = [],
    copts = tf_copts() + [
        "-ffunction-sections",
        "-fdata-sections",
    ],
    linkopts = if_android([
        "-landroid",
        "-latomic",
        "-ldl",
        "-llog",
        "-lm",
        "-z defs",
        "-s",
        "-Wl,--gc-sections",
        "-Wl,--version-script",  # This line must be directly followed by LINKER_SCRIPT.
        LINKER_SCRIPT,
    ]),
    linkshared = 1,
    linkstatic = 1,
    tags = [
        "manual",
        "notap",
    ],
    deps = [
        "//tensorflow/core:android_tensorflow_lib",
        LINKER_SCRIPT,
    ],
)

还有version_script.lds的内容:

{
  global:
    extern "C++" {
        tensorflow::*;
    };
  local:
    *;
};

这将使 tensorflow 命名空间中的所有内容成为全局并可通过库使用,同时隐藏重置并防止它与 protobuf 冲突。

(为此浪费了大量时间,希望对您有所帮助!)

【讨论】:

    【解决方案4】:

    该错误抱怨 Protocol Buffer 运行时库,它与安装的版本不兼容。此错误来自 GTK3 库。 GTK3 使用协议缓冲区 2.6.1。如果你使用 GTK3 来支持 Opencv,你会得到这个错误。解决此问题的最简单方法是使用 QT 而不是 GTK3。

    如果你使用 Cmake GUI 安装 Opencv,只需选择 QT support 而不是使用 GTK3。您可以使用以下命令安装 QT。

    sudo apt install qtbase5-dev 
    

    【讨论】:

      【解决方案5】:

      -Dprotobuf_BUILD_SHARED_LIBS=ON重建libprotobuf

      然后make install 覆盖旧版本

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-13
        • 1970-01-01
        • 2016-03-15
        相关资源
        最近更新 更多