将std::__cxx11::string转换为std::string

90

我使用c++11,但还需要一些未配置其支持的库,并需要进行一些类型转换。特别是我需要一种方法将std::__cxx11::string转换为常规的std::string,但在搜索时我无法找到一种方法来实现这一点,加上(string)也没有效果。

如果我不进行转换,我会得到类似于以下的链接错误:

undefined reference to `H5::CompType::insertMember(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, H5::DataType const&) const'

1
错误听起来更像是编译器找不到 insertMember() 方法。 - Brandlingo
1
嗯,我有其他不使用c++11的程序可以找到它。 - jorgen
1
此外,我猜测您正在使用gcc。我期望在字符串头文件的std命名空间中有一些typedef __cxx11::basic_string basic_string 代码。您是否也编译了包含H5 :: CompType 的编译单元? - Brandlingo
5
我使用C++11,但同时也使用了一些未配置为其的库。这种情况很棘手,你不能真正指望这些东西能够正常工作。请参考以下链接:https://gcc.gnu.org/wiki/Cxx11AbiCompatibility https://web.archive.org/web/20170210052503/http://developerblog.redhat.com/2015/02/05/gcc5-and-the-c11-abi 等等。 - n. m.
4
在解决问题后,我找到了这个问题,所以我想分享一下。问题在于我使用的是gcc而不是g++进行编译... - Aaron Franke
显示剩余5条评论
9个回答

124

你是否在使用 GCC 5?

如果你得到了关于没有定义 std::__cxx11 命名空间中的类型或标签 [abi:cxx11] 的符号的链接错误,那么很可能表明你正试图链接一起编译时使用不同 _GLIBCXX_USE_CXX11_ABI 宏值的目标文件。当链接到使用较旧版本 GCC 编译的第三方库时,这种情况很常见。如果不能使用新的 ABI 重新构建第三方库,则需要使用旧 ABI 重新编译代码。

来源: GCC 5 发布说明/Dual ABI

在包含任何标准库头文件之前定义以下宏将解决您的问题:#define _GLIBCXX_USE_CXX11_ABI 0


4
我尝试了这个,现在在使用c++11函数的任何地方都出现了链接错误。也许没有办法让它同时与c++11和已编译的hdf5库一起工作。 - jorgen
1
对我而言,在Ubuntu 14.04上,g++ 6.2默认编译时将其设置为0;而在16.04上,相同版本的g++编译时将其设置为1。在14.04上,将其设置为1似乎实际上并没有做什么,生成的目标文件并没有使用CXX11 ABI。我怀疑这是一个系统限制。 - Devin Lane
我不确定为什么编译器会抛出“未定义的引用”错误,在寻找解决方案之前,我检查了程序中的所有链接,但没有发现任何问题。之后,我决定在网上搜索并找到了这个解决方法。它非常有效,谢谢 :) - Shravan40
1
非常感谢你!你救了我于一个持续20多个小时的调试噩梦!上帝保佑你! - Hossein

60
如果您可以重新编译所有不兼容的库,请使用编译器选项-D_GLIBCXX_USE_CXX11_ABI=1进行操作,然后重新构建项目。如果您无法这样做,请在您的项目makefile中添加编译器选项-D_GLIBCXX_USE_CXX11_ABI=0。
定义#define _GLIBCXX_USE_CXX11_ABI 0/1也很好,但您可能需要将其添加到所有文件中,而编译器选项会一次性为所有文件添加。请注意保留原有的html标签格式。

5
编译器标志对我有用。谢谢。我因为gcc中这个愚蠢的更改浪费了4天时间! - Behrouz.M

11
当我遇到类似问题时,是因为我的库是使用clang++构建的,并且在我的系统上默认链接到libstdc++.so。而应用程序二进制文件是使用clang构建的,并且使用-lc++选项链接。
检查依赖关系的最简单方法是执行ldd libName.so 要解决此问题,您应该在应用程序和库中使用相同的库。
以下是几种解决方法:
  • 最简单的方法。使用clang++构建库,并在两个步骤中都没有额外的链接选项使用clang++编译应用程序。将使用默认的stdlib。

  • 使用-stdlib=c++构建库,使用-lc++编译应用程序。在这种情况下,库和应用程序都将使用libc++.so

  • 不使用任何额外选项构建库,并将二进制文件链接到-lstdc++。在这种情况下,库和应用程序都将使用libstdc++.so


我也遇到了类似的问题,链接失败的库是使用不同版本的gcc编译的。通过使用ldd命令,我找到了正确的gcc版本,将在新的编译中使用它。 - Krishna Oza

5

这里的答案主要关注快速修复的方法,但如果这些方法不能解决问题,我会提供一些检查步骤(仅适用于Linux):

  • 如果链接其他库时出现链接器错误,请使用调试符号("-g" GCC标志)构建这些库。
  • 列出库中的符号,并搜索链接器抱怨的符号(在命令行中输入以下命令):

    nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout

  • 如果您得到了方法签名,请继续下一步;如果您得到了no symbols,那么您很可能已经从库中剥离了所有符号,这就是为什么链接器在链接库时找不到它们的原因。重新构建库时请勿剥离所有符号,如果需要可以剥离调试符号(strip -S选项)。

  • 使用C++ demangler来理解方法签名,例如这个

  • 将您刚获得的库中的方法签名与您在代码中使用的方法签名进行比较(还要检查头文件),如果它们不同,请使用正确的头文件或正确的库或其他已知的方法来解决问题。

0

对我来说,-D_GLIBCXX_USE_CXX11_ABI=0 没有帮助。

在链接到 C++ 库版本而不是 gnustl 后,它可以工作。


0

我遇到了类似的问题。

原来我的项目使用了gcc 7和g++ 9,并尝试将由这两个编译器编译的目标文件链接在一起,结果出现了混乱。

确保您在整个项目中使用相同版本的编译器。


0

我明白了,我发现唯一解决这个问题的方法是更新所有mingw-64(我使用msys2上的pacman进行了更新)。


0

我最近在尝试链接Ubuntu 16.04上hdf5版本1.10.5的预构建二进制文件时遇到了类似的问题。这里提出的解决方案都没有对我起作用,而我使用的是g++版本9.1。我发现最好的解决方案是从源代码编译hdf5库。不要使用预构建的二进制文件,因为它们是使用gcc 4.9构建的!而应该从hdf website下载特定发行版的源代码档案并构建库。这很容易。

如果您的系统上没有它们,您还需要从herehere获取压缩库zlibszip


0
在我的情况下,我遇到了类似的问题:
/usr/bin/ld: Bank.cpp:(.text+0x19c): undefined reference to 'Account::SetBank(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: error: ld returned 1 exit status

经过一些研究,我意识到问题是由于Visual Studio Code编译Bank.cpp文件的方式引起的。因此,为了解决这个问题,我只需输入以下命令来成功编译c++文件:
g++ Bank.cpp Account.cpp -o Bank

通过上述命令,能够正确地链接头文件、实现文件和主C++文件。
注意:我的g++版本为9.3.0,运行在Ubuntu 20.04上。

我已经使用了这个解决方案和这个链接:https://dev59.com/aVwX5IYBdhLWcg3wjwJZ。如果你在Ubuntu上使用VSC,可以在你的工作目录下的一个名为tasks.json的文件中更改构建命令。"${file}"参数只返回一个要编译的文件。我将我的更改为"${fileDirname}/*.cpp",这将编译项目中所有的cpp文件。请告诉我这个解决方案是否值得尝试,因为我也是在VSC环境中新手。 - Joaozinho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接