G++ and clang++ incompatibility with standard libr

2019-09-11 04:15发布

If I have a file clang.cpp containing:

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

and main.cpp containing:

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

compiling clang++ -g clang.cpp -shared -fPIC -o libclang.so -stdlib=libstdc++ -std=c++11 and clang++ -g main.cpp -L -Wl.,-rpath=. -lclang -lstdc++ -o a.out -stdlib=libstc++ -std=c++11 will run fine.

However, if I add gcc.cpp containing:

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

then also compile that to a shared library using g++ -g gcc.cp -shared -fPIC -o libgcc.so and change the linking command to clang++ -g main.cpp -L -Wl.,-rpath=. -lgcc -lclang -stdlib=libstdc++ -std=c++11 -o a.out, then running ./a.out will segment fault.

I don't know what to make of this, since clang and gcc are supposed to be ABI compatible when using the same c++ standard library. My versions are 3.6.2 for clang, 5.2.1 for gcc, as shipped with ubuntu.

1条回答
不美不萌又怎样
2楼-- · 2019-09-11 05:01

Given

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

Clang generates

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

while GCC generates

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

In other words, Clang is expecting the tuple itself to be passed by register, while GCC is expecting the address to be passed in register (and the tuple passed on the stack).

Mix and match and you get "fun" results.

查看更多
登录 后发表回答