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

Converting std::__cxx11::string to std::string

提问人:jorgen 提问时间:10/28/2015 最后编辑:Baum mit Augenjorgen 更新时间:4/10/2022 访问量:159429

问:

我使用 c++11,但也使用一些未为其配置的库,需要一些类型转换。特别是我需要一种方法来转换为常规,但是谷歌搜索我找不到一种方法来做到这一点,并且放在前面不起作用。std::__cxx11::stringstd::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'
C++ 字符串 C++11 类型 std

评论

1赞 Brandlingo 10/28/2015
这个错误听起来更像是编译器找不到方法。insertMember()
1赞 jorgen 10/28/2015
嗯,它可以在我不使用的其他程序中找到它c++11
1赞 Brandlingo 10/28/2015
此外,我猜您正在使用 gcc。我希望字符串标头的命名空间中有一些。您是否也编译了包含的编译单元?typedef __cxx11::basic_string basic_stringstdH5::CompType
5赞 n. m. could be an AI 10/28/2015
“我使用 c++11,但也使用一些未为其配置的库”。这种情况是有问题的,你不能真的指望东西能起作用。gcc.gnu.org/wiki/Cxx11AbiCompatibility web.archive.org/web/20170210052503/http://... 等等。
4赞 Aaron Franke 3/10/2019
在排除故障后,我找到了解决这个问题的方法,所以我想我会分享,问题是我正在使用而不是编译......gccg++

答:

124赞 Brandlingo 10/28/2015 #1

您是否可能正在使用 GCC 5?

如果收到有关对涉及 std::__cxx11 命名空间或标记 [abi:cxx11] 中的类型的符号的未定义引用的链接器错误,则可能表示您正在尝试将使用 _GLIBCXX_USE_CXX11_ABI 宏的不同值编译的对象文件链接在一起。这通常发生在链接到使用旧版本的 GCC 编译的第三方库时。如果无法使用新的 ABI 重建第三方库,则需要使用旧的 ABI 重新编译代码。

资料来源:GCC 5 发行说明/双 ABI

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

评论

4赞 jorgen 10/29/2015
我试过了;现在,无论我使用 c++11 函数,我都会收到链接器错误。也许没有办法让它同时使用 c++11 和编译的 hdf5 库。
1赞 Devin Lane 9/29/2016
对我来说,在 Ubuntu 14.04 上,g++ 6.2 默认将其设置为 0 进行编译,而在 16.04 上,相同的 g++ 版本将其设置为 1。在 14.04 上,将其设置为 1 似乎实际上没有任何作用;生成的目标文件未使用 CXX11 ABI。我怀疑这是系统限制。
0赞 Shravan40 10/25/2016
我不确定为什么编译器抛出,在寻找解决方案之前,我检查了程序中的整个链接,但没有找到任何东西。在那之后,我决定在网上搜索并找到了这个。它就像魅力一样,谢谢:)undefined reference
1赞 Hossein 9/23/2020
感谢一个四千万次的人!你把我从花了 20+ 小时的调试噩梦中拯救出来!上帝保佑你!
60赞 Denis Sirotkin 5/27/2016 #2

如果您可以重新编译您使用的所有不兼容的库,请使用编译器选项进行编译

-D_GLIBCXX_USE_CXX11_ABI=1

,然后重新生成项目。如果无法执行此操作,请添加到项目的 makefile 编译器选项中

-D_GLIBCXX_USE_CXX11_ABI=0

定义

#define _GLIBCXX_USE_CXX11_ABI 0/1

也很好,但您可能需要将其添加到所有文件中,而编译器选项一次对所有文件执行此操作。

评论

5赞 Behrouz.M 8/14/2016
编译器标志对我有用。谢谢。我浪费了 4 天时间进行 gcc 的这个愚蠢的更改!
0赞 ceorron 6/29/2017 #3

我明白了,我发现解决这个问题的唯一方法是更新所有 mingw-64(我在 msys2 上使用 pacman 执行此操作以供您参考)。

0赞 Dmytro 5/24/2018 #4

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

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

5赞 rightaway717 7/3/2019 #5

这里的答案主要集中在修复它的捷径上,但如果这没有帮助,我会给出一些步骤来检查,这对我有帮助(仅限 Linux):

  • 如果在链接其他库时发生链接器错误,请使用调试符号(“-g”GCC 标志)构建这些库
  • 列出库中的符号,并 grep 链接器抱怨的符号(在命令行中输入命令):

    nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout

  • 如果您获得了方法签名,请继续下一步,如果您获得了签名,则很可能您从库中剥离了所有符号,这就是链接器在链接库时找不到它们的原因。在不剥离所有符号的情况下重建库,如果需要,可以剥离调试(选项)符号。no symbolsstrip -S

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

  • 将您刚刚获得的库中的方法签名与您在代码中使用的方法签名进行比较(也要检查头文件),如果它们不同,请使用正确的标头或正确的库或您现在知道的任何其他方法来修复它
11赞 Evgen Bodunov 7/30/2019 #6

当我遇到类似的问题时,它发生了,因为我的库是使用 构建的,并且默认情况下它在我的系统上链接到。而应用程序二进制文件是使用选项构建并链接的。clang++libstdc++.soclang-lc++

检查依赖关系的最简单方法是执行ldd libName.so

要修复它,您应该在应用程序和库中使用相同的库。

  • 最简单的方法。使用 构建库并使用 编译应用程序。两个步骤都没有额外的链接选项。将使用默认的 stdlib。clang++clang++

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

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

评论

0赞 Krishna Oza 8/1/2023
我还有一个类似的问题,链接失败的库是使用不同版本的 gcc 编译的,使用帮助识别我将用于新编译的 gcc 的正确版本ldd
0赞 unbound37 12/18/2019 #7

我最近在尝试与 Ubuntu 16.04 上的 hdf5 版本 1.10.5 的预构建二进制文件链接时遇到了类似的问题。这里建议的解决方案都不适合我,我使用的是 g++ 9.1 版。我发现最好的解决方案是从源代码构建 hdf5 库。不要使用预构建的二进制文件,因为它们是使用 gcc 4.9 构建的!相反,请从 hdf 网站下载特定发行版的源代码存档并构建库。这很容易。

如果您的系统上还没有压缩库 zlibszip,则还需要分别从此处此处 获取它们。

0赞 Tiago Sá 10/18/2020 #8

就我而言,我遇到了类似的问题:

/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

使用上面的命令,它能够正确链接 Header、Implementations 和 Main c++ 文件。

OBS:我的 g++ 版本:Ubuntu 9.3.0 上的 20.04

评论

0赞 Joaozinho 6/1/2023
我用过这个解决方案和这个解决方案:stackoverflow.com/questions/33662375/...。如果您在 ubuntu 上使用 VSC,请在工作目录中名为 tasks.json 的文件下更改您的生成命令。读取 CPP 文件“${file}”的参数,它只返回 1 个要编译的文件。我将我的更改为“${fileDirname}/*.cpp”,这将编译您项目下的所有 cpp。请让我知道我这个解决方案是值得的,也是VSC环境的新手。
0赞 Ohad Cohen 4/10/2022 #9

我遇到过类似的问题

事实证明,我的项目使用的是 gcc 7 和 g++ 9,并试图将这两个编译的对象文件链接在一起,但一切都搞砸了。

确保在所有项目中使用相同的编译器版本。