20

I see a fair amount of questions like Apple Mach-O Linker (Id) Error and Undefined symbols in cryptopp at IOS 64-bit project. The problem is usually described as:

Undefined symbols for architecture i386:
  "std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush()", referenced from:
      cv::gpu::error(char const*, char const*, int, char const*) in opencv2(gpumat.o)

The problem often reduces to mixing/matching -stdlib=libc++ (LLVM C++ runtime) and -stdlib=libstdc++ (GNU C++ runtime). The LLVM C++ runtime (libc++) has an __1 decoration symbol, but the GNU C++ runtime libstdc++ lacks the __1 symbol in its name. It causes linker problems for symbols that appears to have the same name (like std::string).

Where does the __1 symbol come from when using LLVM's libc++?

Why was the problem not solved with a gnu namespace and an llvm namespace?


Here's a related question: libc++ - stop std renaming to std::__1?. But it kind of misses the point in that a rename does not occur.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

14

It is from C++11 inlined namespaces

libc++ has something like

namespace std {
    inline namespace __1 {
        ....

more at What are inline namespaces for?

Community
  • 1
  • 1
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • Thanks @Severin. That's an interesting link. So *if* I used a C++11 compiler, the the problems with `std::string` and `std::__1::string` would go away becuase the compiler would understand the inline namespace? Or the problem would go away if I used `-std=c++03` because inline namespaces would not be used? (Up until now, I've been telling people to compile everything with either the LLVM runtime or the GNU runtime). – jww Mar 27 '15 at 04:48
  • 2
    @jww I believe both compilers (GCC and clang) understand inlined namspaces. Problem is with declaration vs definition. If you're using libc++ headers, you'll get declarations picked with `std::__1::` prefix, something like `std::__1::string` etc. If you're using GNU libstdc++ header, you'll get declaration `std::string` etc. But then you have to pick up definitions from either libstdc++.a/.so or from libc++.a/.so. Due to the fact, that each library is compiled with it's own headers, definitions also carry the same prefix. To be continued... – Severin Pappadeux Mar 27 '15 at 04:59
  • 2
    Thus, if you pick declarations from libc++ headers (with std::__1:: prefix) but try to use definitions from libstdc++ (with std:: prefix), you're getting linker error - definitions don't much. Good thing, I think, debugging might be a nightmare. So I would say if you're using GNU toolchain, link against libstdc++, if clang - link against libc++ – Severin Pappadeux Mar 27 '15 at 05:01
  • 1
    Just to be clear - those prefixes are in mangled names in compiled code in .o/.a/.so. In source code you see/use std::string. – Severin Pappadeux Mar 27 '15 at 05:07
  • It would be nice to have a solution to the resulting compilation problem, though. – Oscar Aug 11 '22 at 01:18