构建共享库时,G ++和clang ++与标准库不兼容?

时间:2016-02-23 19:23:20

标签: c++ gcc clang compiler-bug

如果我有一个文件clang.cpp包含:

#include <map>
void myfunc() {
    std::map<int, int> mymap;
    const int x = 20;
    myfoo[x] = 42;
}

和main.cpp包含:

void myfunc();
int main() { myfunc(); }

编译clang++ -g clang.cpp -shared -fPIC -o libclang.so -stdlib=libstdc++ -std=c++11clang++ -g main.cpp -L -Wl.,-rpath=. -lclang -lstdc++ -o a.out -stdlib=libstc++ -std=c++11运行正常。

但是,如果我添加包含以下内容的gcc.cpp:

#include <tuple>
template std::pair<int const, int>::pair(std::piecewise_construct_t, std::tuple<int const&>, std::tuple<>);

然后使用g++ -g gcc.cp -shared -fPIC -o libgcc.so将其编译到共享库,并将链接命令更改为clang++ -g main.cpp -L -Wl.,-rpath=. -lgcc -lclang -stdlib=libstdc++ -std=c++11 -o a.out,然后运行./a.out将分段错误。

我不知道该怎么做,因为在使用相同的c ++标准库时,clang和gcc应该是ABI兼容的。我的版本是clang的3.6.2,gcc的5.2.1,与ubuntu一起提供。

1 个答案:

答案 0 :(得分:3)

鉴于

int f(std::tuple<const int &> t){
  return std::get<0>(t);
}

Clang生成

f(std::tuple<int const&>):                    # @f(std::tuple<int const&>)
        movl    (%rdi), %eax
        retq

而GCC生成

f(std::tuple<int const&>):
        movq    (%rdi), %rax
        movl    (%rax), %eax
        ret

换句话说,Clang期望元组本身通过寄存器传递,而GCC期望地址在寄存器中传递(并且元组在堆栈上传递)。

混合搭配,你会得到“有趣”的结果。