使用clang ++和O2的未定义引用

时间:2014-04-09 19:46:20

标签: c++ c++11 clang clang++ libc++

我在一个项目上尝试了CLang 3.4和libc ++,我在发布模式下遇到奇怪的链接错误:

/home/wichtounet/dev/eddic/src/ast/Operator.cpp:17: error: undefined reference to
'std::__1::basic_ostream<char, std::__1::char_traits<char>>&
 std::__1::operator<< <char, std::__1::char_traits<char>, std::__1::allocator<char>>(
   std::__1::basic_ostream<char, std::__1::char_traits<char>>&,
   std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&
 )'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

一切都很好。程序在调试模式下正确链接,但在使用O2时没有。在O0,O1和Os中,一切正常,但它在O2,O3,Os中没有链接。我也试过LTO模式,它工作正常。

我尝试了两个版本的libc ++,但无济于事。

代码对我来说似乎并不坏:

std::ostream& ast::operator<< (std::ostream& stream, ast::Operator op){
    std::string value = "asd";
    return stream << value;
}

但我没有一个简单的例子导致问题。

clang ++用于构建和链接代码。我用&#34; -std = c ++ 1y -stdlib = libc ++&#34;编译和相同的加上一些库的东西来链接。

可能导致什么?

编辑:在发布模式下完全调用链接步骤:

clang++ -v -use-gold -Iinclude -std=c++1y -stdlib=libc++ -Wextra -Wall -Qunused-arguments -Wuninitialized -Wsometimes-uninitialized -Wno-long-long -Winit-self -Wdocumentation -pedantic -isystem /home/wichtounet/build/modular-boost//include -L /home/wichtounet/build/modular-boost//lib -lboost_program_options -g -DLOGGING_DISABLE -DNDEBUG -O3 -march=native -fvectorize -fslp-vectorize-aggressive -fomit-frame-pointer -o release/bin/eddic "TONS OF DOT O"
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
Selected GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2
 "/usr/bin/x86_64-pc-linux-gnu-ld" --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o release/bin/eddic /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/crtbegin.o -L/home/wichtounet/build/modular-boost//lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../.. -L/lib -L/usr/lib -lboost_program_options "TONS OF DOT O" -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/../../../../lib64/crtn.o
src/ast/Operator.cpp:15: error: undefined reference to 'std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<< <char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

2 个答案:

答案 0 :(得分:4)

我在使用g ++编译的代码中遇到此问题,尝试使用clang ++进行编译。相同的症状:对std :: __ 1 :: basic_ostream的未定义引用&lt; ...&gt;当从编译器选项中删除-O2时,神奇地消失了。我发现的所有类似报告都是错误地使用clang而不是clang ++来编译C ++代码,但对我来说情况并非如此:我使用的是clang ++。

我终于能够确定问题(对我而言)在我的标题(.h)文件中使用#include <iosfwd>(仅具有iostream前向声明,以减少编译时间)声明一个类但不使用实现该类的相应源(.cpp)文件中的#include <iostream>

#include <iostream>添加到源文件并重新编译后,这些未定义的引用错误就消失了。

答案 1 :(得分:1)

我在错误消息“std :: __ 1 :: operator&lt;&lt;”中注意到了。在cpp代码中,我看到“ast :: operator&lt;&lt;”。 这给人的印象是,命名空间会出现问题。

现在我不知道 ast 是一个类还是一个命名空间,但在这两种情况下都看起来有些偏差。

如果 ast 是一个类,那么我不确定运算符&lt;&lt;被允许作为班级成员。看到: http://www.cs.nctu.edu.tw/cis/chinese/doc/research/c++/C++FAQ-English/input-output.html#faq-15.8。它表明运营商&lt;&lt;应该作为朋友实施,而不是作为班级成员。您可以尝试将其设为朋友方法,看看是否能解决问题。

如果 ast 是命名空间,那么我会尝试删除“asd ::”,并在定义周围添加单独的命名空间声明。