[英]c++ undefined reference to a class member function
I encountered the following linking issues when trying to use librbd.我在尝试使用 librbd 时遇到了以下链接问题。
The following is my code snippet.以下是我的代码片段。
#include <iostream>
#include <rados/librados.hpp>
#include <rbd/librbd.hpp>
int main(){
// Initialize and open an rbd image
std::string pool = "xxx";
std::string image_name = "xxxx";
int r;
librados::Rados cluster;
librados::IoCtx io_ctx;
librbd::Image image;
librbd::RBD rbd;
r = cluster.init("cinder-ctest");
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::string id;
image.get_id(&id); // <- Where the problem occurs
std::cerr << id << std::endl;
return 0;
}
An error occurred when I compiled using the following command我使用以下命令编译时发生错误
$ g++ main.cc -o info -lrbd -lrados
/tmp/ccOpSFrv.o: In function `main':
main.cc:(.text+0x12b): undefined reference to `librbd::Image::get_id(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
collect2: error: ld returned 1 exit status
but I use nm to see that get_id exists:但我使用 nm 来查看 get_id 存在:
$ nm -D /usr/lib64/librbd.so | grep get_id
0000000000083d00 T rbd_get_id
000000000008de10 T _ZN6librbd5Image6get_idEPSs
U _ZN8librados7v14_2_05IoCtx6get_idEv
and it is globally visible:它是全球可见的:
$ readelf -s /usr/lib64/librbd.so | grep get_id
498: 0000000000083d00 70 FUNC GLOBAL DEFAULT 11 rbd_get_id
559: 000000000008de10 54 FUNC GLOBAL DEFAULT 11 _ZN6librbd5Image6get_idEP
why do I get an error when compiling: undefined reference to librbd::Image::get_id
.为什么在编译时出现错误:未定义引用
librbd::Image::get_id
。 It clearly exists, which makes me wonder.它显然存在,这让我感到奇怪。
Some background: C++11 changed the std::string
interface slightly by adding noexcept
specifiers to a few member functions, but it turns out that slight change meant that libstdc++ had to re-write their std::string
implementation in a non-ABI-compatible way.一些背景:C ++ 11改变了
std::string
,加入稍接口noexcept
符的几个成员函数,但事实证明,细微的变化意味着的libstdc ++不得不重新编写他们std::string
实现在非ABI 兼容方式。 For backwards compatibility, they retained the old version and put the new one in an inline namespace so it's named std::__cxx11::basic_string
as far as the linker is concerned.为了向后兼容,他们保留了旧版本并将新版本放在一个内联命名空间中,因此就链接器而言,它被命名为
std::__cxx11::basic_string
。 See this page for more info.有关更多信息,请参阅此页面。
That's where you're running into trouble.这就是你遇到麻烦的地方。
_ZN6librbd5Image6get_idEPSs
demangles to _ZN6librbd5Image6get_idEPSs
为
librbd::Image::get_id(
std::basic_string<
char,
std::char_traits<char>,
std::allocator<char>
>*
)
That function accepts the old version of std::string
, but you're passing it a pointer to the new version of std::string
.该函数接受旧版本的
std::string
,但您将指针传递给新版本的std::string
。 Presumably the version of librbd you have was either built with an old version of GCC, or was purposely built against the old ABI.据推测,您拥有的 librbd 版本要么是用旧版本的 GCC 构建的,要么是专门针对旧 ABI 构建的。
You have a few options to work around this:您有几个选项可以解决此问题:
_GLIBCXX_USE_CXX11_ABI
preprocessor macro to 0
to tell libstdc++ to use the old implementation of std::string
._GLIBCXX_USE_CXX11_ABI
预处理器宏定义为0
以告诉 libstdc++ 使用std::string
的旧实现。 It doesn't technically fully comply with C++11 and later standard revisions, but it's mostly the same.Seems like you use a C++11-compatible compiler, that generates _ZN6librbd5Image6get_idEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
names, but your library was compiled using C++03, C++98 or something like that, before C++11.似乎您使用 C++11 兼容编译器,它生成
_ZN6librbd5Image6get_idEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
名称,但您的库是使用 C++03、C++98 或类似的东西编译的,在 C++11 之前。
If you have access to the library sources, recompile it with C++11, if you don't, compile your program in the C++03 compatibility mode.如果您可以访问库源代码,请使用 C++11 重新编译它,如果没有,请在 C++03 兼容模式下编译您的程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.