`_GLIBCXX_USE_CXX11_ABI`有什么作用

最近遇到个问题,在链接OpenVINO的时候,需要将libinference_engine.so与libinference_engine_legacy.so都链接进去,但如果在CMakeLists里设置add_definitions(-D _GLIBCXX_USE_CXX11_ABI=0),就无法正常链接:编译器只会链接libinference_engine_legacy.so,而没有libinference_engine.so,当设置add_definitions(-D _GLIBCXX_USE_CXX11_ABI=1),就不会出现这样的情况。并且后续会报出符号未定义的错,如下所示。

my_lib.so: undefined reference to `InferenceEngine::Core::LoadNetwork(InferenceEngine::CNNNetwork, std::string const&, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > > const&)'
my_lib.so: undefined reference to `InferenceEngine::Data::getName() const'
my_lib.so: undefined reference to `InferenceEngine::Core::Core(std::string const&)'
my_lib.so: undefined reference to `InferenceEngine::details::InferenceEngineException::InferenceEngineException(std::string const&, int, std::string const&)'
my_lib.so: undefined reference to `InferenceEngine::Core::ReadNetwork(std::string const&, std::string const&) const'

这就比较诡异了,必须好好看看这个_GLIBCXX_USE_CXX11_ABI有什么作用。

参考GCC提供的手册<Dual ABI>,大概的意思就是说。

在GCC5.1发布的同时,为libstdc++添加了新的特性,其中也包括了std::string和std::list的新实现。这个新的实现使得两者符合了c++11的标准,具体来说是取消了Copy-On-Write。那么,这样子虽然符合了c++11的标注,旧版不就无法兼容了吗。为了避免上述混乱,对于旧版而言,GCC5.1添加了__cxx11命名空间,GCC5.1或者说c++11规范下的string和list,实际上是std::__cxx11::string和std::__cxx11::list,所以我们一般的using namespace std就会变成形如using namespace std::__cxx11的样子。也就是说,有旧版(c++03规范)的libstdc++.so,和新版(c++11规范)的libstdc++.so两个库同时存在。

为了避免两个库到底选择哪一个的麻烦,GCC5.1就引入了-D_GLIBCXX_USE_CXX11_ABI来控制编译器到底链接哪一个libstdc++.so,

-D_GLIBCXX_USE_CXX11_ABI=0 链接旧版库
-D_GLIBCXX_USE_CXX11_ABI=1 链接新版库
所以,回到OpenVINO的那个问题,提示符号未定义,我估计就是因为,OpenVINO这个第三方的库libinference_engine.so,它是使用c++11规范的libstdc++.so,所以我在引用的时候,也必须使用相同规范的libstdc++.so,否则在这个第三方的内部,std::string就必须改成std::__cxx11::string才能使用_GLIBCXX_USE_CXX11_ABI=0。大概就是这样子,又学习了呢。


原文链接:https://blog.csdn.net/github_28260175/article/details/105922130

posted @ 2021-11-22 20:56  鸭子船长  阅读(881)  评论(0编辑  收藏  举报