C++ c++;对类成员函数的未定义引用
我在尝试使用librbd时遇到了以下链接问题 下面是我的代码片段C++ c++;对类成员函数的未定义引用,c++,librbd,C++,Librbd,我在尝试使用librbd时遇到了以下链接问题 下面是我的代码片段 main.cc #包括 #包括 #包括 int main(){ //初始化并打开rbd映像 std::string pool=“xxx”; std::string image_name=“xxxx”; INTR; librados::Rados集群; librados::IoCtx io_ctx; librbd::图像; librbd::RBD-RBD; r=簇的初始值(“煤渣测试”); r=cluster.connect()
- main.cc
#包括
#包括
#包括
int main(){
//初始化并打开rbd映像
std::string pool=“xxx”;
std::string image_name=“xxxx”;
INTR;
librados::Rados集群;
librados::IoCtx io_ctx;
librbd::图像;
librbd::RBD-RBD;
r=簇的初始值(“煤渣测试”);
r=cluster.connect();
r=cluster.ioctx_create(pool.c_str(),io_ctx);
r=rbd.open_read_only(io_ctx,image,image_name.c_str(),NULL);
std::字符串id;
image.get_id(&id);//看起来您使用的是一个与C++11兼容的编译器,它生成\u zn6libbd5image6get_idEPNSt7\u cxx1112basic\u stringIcSt11char\u traitsIcESaIcEEE
名称,但您的库是在C++11之前使用C++03、C++98或类似的东西编译的
如果您可以访问库源代码,请使用C++11重新编译它,如果您没有,请在C++03兼容模式下编译您的程序。一些背景:C++11通过向一些成员函数添加noexcept
说明符略微更改了std::string
接口,但事实证明,这一细微的更改意味着libstdc++必须以不兼容ABI的方式重新编写其std::string
实现。为了向后兼容,他们保留了旧版本,并将新版本放在内联命名空间中,因此就链接器而言,它被命名为std::u cxx11::basic_string
。有关更多信息,请参阅
这就是你遇到麻烦的地方。\u zn6libbd5image6get\u idEPSs
demangles to
librbd::Image::get_id(
std::basic_string<
char,
std::char_traits<char>,
std::allocator<char>
>*
)
librbd::Image::get\u id(
基本字符串<
烧焦
性病:性格特征,
分配器
>*
)
该函数接受旧版本的std::string
,但您正在向它传递一个指向新版本的std::string
的指针。您所使用的librbd版本可能是使用旧版本的GCC构建的,也可能是专门针对旧的ABI构建的
您有几个选项可以解决此问题:
查找为libstdc++的新ABI构建的librbd版本。
- 如果您使用的版本来自发行版的软件包管理器,您可能需要查看其他地方(如Conan或vcpkg或其他)
根据新的ABI构建librbd。
- 我不熟悉那个库,所以我不知道这有多难。似乎在一些发行版上他们的工具链
根据旧ABI构建应用程序。
- 正如我上面链接的页面所说,您可以将
\u GLIBCXX\u USE\u cx11\u ABI
预处理器宏定义为0
,告诉libstdc++使用std::string
的旧实现。它在技术上并不完全符合C++11和更高版本的标准,但基本上是一样的
执行g++-c main.cc
并检查nm main.o
以查找未定义的get_id
符号。如果它有不同的名称,则您遇到了ABI不兼容问题。@aschepler我认为您是对的,如何解决此类问题?bash$nm main.o | grep get_id U zn6libbd5image6get_idEPNSt7_cx1112基本原则11Char_traitsiceaee
此链接对发生的情况进行了完整的解释,并提供了一些解决方法: