Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;std::文件系统::路径追加上的std::bad_alloc_C++_Exception_Gdb_C++17_Libstdc++ - Fatal编程技术网

C++ c++;std::文件系统::路径追加上的std::bad_alloc

C++ c++;std::文件系统::路径追加上的std::bad_alloc,c++,exception,gdb,c++17,libstdc++,C++,Exception,Gdb,C++17,Libstdc++,我正在经历一个非常奇怪的行为,我将其归结为一个非常基本的测试: #include <string> #include <filesystem> int main(void) { const std::string name = "foo"; const std::filesystem::path lock_dir = "/tmp"; std::filesystem::path lockfile = lock_dir / name; return 0;

我正在经历一个非常奇怪的行为,我将其归结为一个非常基本的测试:

#include <string>
#include <filesystem>

int main(void)
{
  const std::string name = "foo";
  const std::filesystem::path lock_dir = "/tmp";
  std::filesystem::path lockfile = lock_dir / name;

  return 0;
}
这带来了几个问题:

  • 我的测试代码有什么问题
  • 为什么GDB在调用堆栈中显示python的任何内容
  • 考虑到这个问题,我的g++是
    gcc版本8.3.0(Ubuntu 8.3.0-6ubuntu1~18.04.1)
    ,我的gdb是
    GNU gdb(Ubuntu 8.2-0ubuntu1~18.04)8.2

    更新以下是成功编译的可执行文件的ldd输出

    linux-vdso.so.1 (0x00007ffc697b2000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5c35444000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5c3522c000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c34e3b000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5c34a9d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5c35a2d000)
    

    我将用其他人在评论中的发现来总结我自己的发现。这还不是一个实际的答案,因为此时我无法解释失败的原因

    通过在一个常规的
    ubuntu
    Docker映像中安装g++-8和g++-9,我能够重现这种行为,因此我有
    /usr/bin/g++-8
    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.26

    根据
    gdb
    堆栈跟踪,错误发生在
    std::vector
    构造函数的某个地方。当在其
    操作符/
    内调用
    std::filesystem::path
    的默认复制构造函数时,似乎会发生这种情况:

    /usr/include/c++/8/bits/fs\u path.h

    ///将一条路径附加到另一条路径
    内联路径运算符/(常数路径和常数lhs,常数路径和常数rhs)
    {
    路径uu result(u lhs);//这是由Ubuntu的一个“功能”造成的,它提供了比系统附带的
    g++
    更晚的
    libstdc++。因此
    。有关更多详细信息,请参阅

    通常,当使用GCC 8编译时,
    std::filesystem
    符号不在
    libstdc++中。因此,如果您没有这样做,那么您将得到一个链接器错误。但是,由于GCC 9中较新的
    libstdc++.so
    包含
    std::filesystem
    的符号,因此链接器错误不会发生。不幸的是文件系统符号的CC 9版本与GCC 8头不兼容(因为文件系统库在GCC 8中是实验性的且不稳定的,并且对于GCC 9,
    filesystem::path
    的布局已更改)。这意味着您的程序会链接,但在运行时,它使用了错误的符号来表示
    文件系统::path
    ,并且会发生不好的事情

    我没有预料到这个问题,因为我不知道Ubuntu将旧的libstdc++头与新的libstdc++共享库混合在一起


    我为Ubuntu建议的修复方法是使
    g++
    自动将
    -lstdc++fs
    添加到编译命令的末尾。如果您使用任何
    std::filesystem
    功能,那么这些符号的正确定义应该在GCC 8的
    libstdc++fs.a
    中找到(而不是在GCC 9的
    libstdc++.so
    )在大多数情况下,一切都应该正常工作。如果Ubuntu还没有用这种解决方法更新他们的GCC包,你也可以通过确保手动链接到
    -lstdc++fs
    (这是GCC 8所需的文档).

    如果在编译/链接时添加
    -lstdc++fs
    您是否注意到任何差异?@tedlynmo如果没有它,他将有一个链接问题。我想知道在没有
    -lstdc++fs
    的情况下如何使用gcc 8.3.0进行编译。它应该会失败…:-/这里是另一个数据点。在我的坏VM中,我可以用
    g++-std=c++17编译/链接一个坏的可执行文件-Wall-Wextra-Werror-g foo.cpp-o foo
    。当我编译/链接
    g++-std=c++17-Wall-Wextra-Werror-g foo.cpp-o foo-lstdc++fs时,它运行时没有problem@TedLyngmo如果不是因为“功能”,你上面的评论是正确的,而且是100%正确的Ubuntu的。Ubuntu是根据设计为libstdc++提供不一致的头和共享库的,这就是为什么程序链接时不使用
    -lstdc++fs
    ,这就是为什么它在运行时崩溃的原因。有关更多信息,请参阅我下面的答案。它看起来像是构造函数调用了_M_spit_cmpts,这使得向量在某种程度上被阻塞了。“这个问题是由编译器和库版本之间的不兼容引起的”——你是对的,问题是OP没有造成这种不兼容,Ubuntu做到了:-(请参阅我的答案以了解谜题中缺失的部分。谢谢@JonathanWakely-你的答案应该是公认的:)哇…讨厌:-)很高兴知道!我正在运行Ubuntu。@TedLyngmo,是的,如果你忘记了
    -lstdc++fs
    将变成未定义的行为和运行时崩溃,那么链接器应该是错误的。讨厌。根据,现在应该修复,所以请确保你是最新的。我的本地计算机可能会更新,但我可能应该检查一下它们在CI机器中的容器中运行的内容,
    boost::filesystem
    也是混合的一部分。
    linux-vdso.so.1 (0x00007ffc697b2000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5c35444000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5c3522c000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c34e3b000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5c34a9d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5c35a2d000)