clang ++ -stdlib = libc ++导致未定义的引用

时间:2013-08-27 07:51:22

标签: linker-errors clang++ libc++

为什么在将clang与libc ++一起使用时会出现以下链接器错误:

$ clang++ -stdlib=libc++  po.cxx -lpoppler
/tmp/po-QqlXGY.o: In function `main':
po.cxx:(.text+0x33): undefined reference to `Dict::lookup(char*, Object*, std::__1::set<int, std::__1::less<int>, std::__1::allocator<int> >*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

其中:

$ nm -D /usr/lib/x86_64-linux-gnu/libpoppler.so | grep lookup | c++filt| grep \ Dict::lookup\(
00000000000c1870 T Dict::lookup(char*, Object*, std::set<int, std::less<int>, std::allocator<int> >*)

代码很简单:

#include <poppler/PDFDoc.h>

int main()
{
  Dict *infoDict;
  Object obj;
  infoDict->lookup((char*)"key", &obj);
  return 0;
}

3 个答案:

答案 0 :(得分:8)

根据你的错误,它应该像你试图将libc ++与stdlibc ++链接, libc ++和stdlibc ++不同,stdlibc ++是gcc的c ++标准库,它不会相互兼容。

对于你的问题,就像你的libpoppler.so正在使用stdlibc ++, 但是在你的clang命令行中,你正在尝试使用libc ++作为标准库,它们在链接阶段有不同的名称,请参阅本答案末尾的链接以了解详细原因。

所以,也许你的解决方案只是将编译命令更改为

    clang++ -stdlib=libstdc++  po.cxx -lpoppler

请详细说明std:__ 1 :: set和std :: set。

的详细信息

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

答案 1 :(得分:4)

因为libpoppler.so与GNU stdlibc ++相关联。单个可执行文件的所有部分都必须链接到相同的标准C和相同的标准C ++库。

最简单的选择是使用默认的标准库。现在两者都是C ++ 11完成的。

或者,您可以针对libpoppler.so构建libc++的版本,但是您必须为其指定不同的名称,以便动态链接器找到正确的名称。

在链接错误中,您可以看到libpoppler.so引用std::setstd::less等,但您的对象想要引用std::__1::setstd::__1::less这是因为GNU stdlibc ++和Clang libc ++以不同的方式进行版本控制。

答案 2 :(得分:3)

因为libc ++使用与GNU C ++标准库不同的命名空间。这个链接器错误是一件好事,因为对于某些类型,两个库的类型的布局肯定会有所不同。

所以这意味着你的'poppler'库是针对GNU C ++ std库构建的,它有一组名称 - 而编译器使用libc ++中的声明来实现程序翻译中的函数调用。因此,链接器在对象(例如poppler库)中查找具有std库声明的libc ++命名的符号,但它找不到它们,因为它们不是以相同的名称发出的 - 它们可能存在于poppler库中使用GNU名称。

当然,您可能只关心如何解决这个问题:使用相同的标准库构建程序和poppler库。如果你不能构建poppler库,你将不得不等待它们推出一个针对libc ++构建的二进制文件。