我最近一直试图在Windows上改变我的C ++工作,到目前为止,所有东西似乎都正常工作,除了一件事:制作完全静态的excecutables(没有任何外部dll依赖,如libgcc libstdc ++等......)。
让我举个例子。 我们有以下简单程序:
#include <string>
int main()
{
std::string s1 = "Happy";
std::string s2 = " Cow";
std::string s3 = s1 + s2;
return 0;
}
如果我们尝试使用以下行编译它:
clang++ -static -O0 -std=c++11 bug.cpp
我们收到以下链接错误:
F:/Programs/LLVM/bin/../lib/gcc/i686-w64-mingw32/4.8.2\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_[__ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_]+0x0): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
C:\Users\THEART~1\AppData\Local\Temp\bug-4d96cd.o:(.text[__ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_]+0x0): first
defined here
collect2.exe: error: ld returned 1 exit status
clang++.exe: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)
我们使用以下标志得到相同的结果:
clang++ -static -static-libgcc -static-libstdc++ -O0 -std=c++11 bug.cpp
应该注意的是,当使用g ++时,程序可以编译并与上述两行中的任何一行完美链接。显然当删除静态标志时,程序也可以用clang编译得很好。
这个bug一直在追我几个星期,所以昨晚我全力以赴,开始寻找可能导致它的任何事情。经过几个小时的挖掘,我认为我应该检查并比较两个编译器的中间输出。
查看clang生成的目标文件的符号,我看到了:
nm bug_clang.o
--------------------
00000000 b .bss
00000000 d .data
00000000 d .eh_frame
00000000 r .gcc_except_table
00000000 r .rdata
00000000 t .text
00000000 t .text
00000001 a @feat.00
U ___gxx_personality_v0
U ___main
U __Unwind_Resume
U __ZNSaIcEC1Ev
U __ZNSaIcED1Ev
U __ZNSs6appendERKSs
U __ZNSsC1EPKcRKSaIcE
U __ZNSsC1ERKSs
U __ZNSsD1Ev
00000000 T __ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 T _main
00000000 r GCC_except_table0
00000048 r GCC_except_table1
检查g ++生成的目标文件上的符号时,给了我:
nm bug_g++.o
00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .eh_frame$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 d .gcc_except_table
00000000 r .rdata
00000000 r .rdata$zzz
00000000 t .text
00000000 t .text$_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
U ___gxx_personality_v0
U ___main
U __Unwind_Resume
U __ZNSaIcEC1Ev
U __ZNSaIcED1Ev
U __ZNSs6appendERKSs
U __ZNSsC1EPKcRKSaIcE
U __ZNSsC1ERKSs
U __ZNSsD1Ev
00000000 r __ZStL19piecewise_construct
00000000 T __ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
00000000 T _main
正如您所看到的,g ++生成的目标文件中有一些内部符号根本不存在或者在clang生成的目标文件中有所不同,即:
(我认为它与异常处理有关)
(我相信这个也存在于clang对象文件中,作为第二个“00000000 t .text”条目)
我对这个问题没有真正深入的了解,但我的赌注是,在clang生成的目标文件中改变的第二个内部符号(我在上面提到的那个)是问题的根本原因。
这是clang编译器的错误,还是我做错了什么?
如果你问,我在使用本指南设置的Windows上使用LLVM v3.6和MinGW-w64 4.8.2:https://yongweiwu.wordpress.com/2014/12/24/installing-clang-3-5-for-windows/
另外我可能会注意到,在尝试查找问题原因时,另一个真正让我失望的原因是,如果我尝试使用-O2编译代码片段,由于编译器的内联工作,一切正常!
我真的希望有人能帮我解决这个问题,因为它让我疯了!