在std :: filesystem :: path追加上的c ++ std :: bad_alloc

保罗·格林伯格

我遇到了一个非常奇怪的行为,我将其简化为一个非常基本的测试:

#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;
}

我用编译g++ -std=c++17 -Wall -Wextra -Werror -g foo.cpp -o foo当我运行它时,在附加两个路径的那一行上,我得到了一个std :: bad_alloc异常。这是我在gdb中看到的

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff742c801 in __GI_abort () at abort.c:79
#2  0x00007ffff7a8e1f2 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7a99e36 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff7a99e81 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff7a9a0b5 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7a907a7 in std::__throw_bad_alloc() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x0000555555558cfe in __gnu_cxx::new_allocator<std::filesystem::__cxx11::path::_Cmpt>::allocate (this=0x7fffffffe080, __n=12297828079348111650) at /usr/include/c++/8/ext/new_allocator.h:102
#8  0x00005555555587d0 in std::allocator_traits<std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::allocate (__a=..., __n=12297828079348111650) at /usr/include/c++/8/bits/alloc_traits.h:436
#9  0x0000555555557f76 in std::_Vector_base<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::_M_allocate (this=0x7fffffffe080, __n=12297828079348111650)
    at /usr/include/c++/8/bits/stl_vector.h:296
#10 0x0000555555558387 in std::_Vector_base<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::_M_create_storage (this=0x7fffffffe080, __n=12297828079348111650)
    at /usr/include/c++/8/bits/stl_vector.h:311
#11 0x00005555555579cf in std::_Vector_base<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::_Vector_base (this=0x7fffffffe080, __n=12297828079348111650, __a=...)
    at /usr/include/c++/8/bits/stl_vector.h:260
#12 0x0000555555556d39 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::vector (this=0x7fffffffe080, 
    __x=std::vector of length -1303124922760, capacity -1303124922760 = {...}) at /usr/include/c++/8/bits/stl_vector.h:460
#13 0x000055555555635f in std::filesystem::__cxx11::path::path (this=0x7fffffffe060, Python Exception <class 'gdb.error'> There is no member or method named _M_t.: 
__p=...) at /usr/include/c++/8/bits/fs_path.h:166
#14 0x00005555555563c8 in std::filesystem:: (Python Exception <class 'gdb.error'> There is no member or method named _M_t.: 
__lhs=..., Python Exception <class 'gdb.error'> There is no member or method named _M_t.: 
__rhs=...) at /usr/include/c++/8/bits/fs_path.h:554
#15 0x0000555555555fbe in main () at foo.cpp:8

这带来了几个问题:

  1. 我的测试代码有什么问题?
  2. 为什么GDB在调用堆栈中使用python显示任何内容?

预料到这个问题,我的g ++gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1~18.04.1)和我的gdb是GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2

UPDATE这是成功编译的可执行文件的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)
阿芬斯特

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

通过在常规ubuntuDocker映像中安装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在其内部调用默认复制构造函数时发生operator/

/usr/include/c++/8/bits/fs_path.h

  /// Append one path to another
  inline path operator/(const path& __lhs, const path& __rhs)
  {
    path __result(__lhs);  // <-- fails here
    __result /= __rhs;
    return __result;
  }

这一发现可以进一步简化测试用例:

#include <filesystem>

int main(void)
{
  const std::filesystem::path first = "/tmp";
  const std::filesystem::path second(first);

  return 0;
}

这清楚表明问题出在调用复制构造函数时。

唯一的vector输入std::filesystem::path是此向量(大概是路径分量):

/usr/include/c++/8/bits/fs_path.h

    struct _Cmpt;
    using _List = _GLIBCXX_STD_C::vector<_Cmpt>;
    _List _M_cmpts; // empty unless _M_type == _Type::_Multi

根据堆栈跟踪,复制此向量时,我们立即进入stl_vector.h

/usr/include/c++/8/bits/stl_vector.h

      vector(const vector& __x)
      : _Base(__x.size(),
        _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
      {

但是,如果我们__n_Vector_basehere的构造函数中打印的值

      _Vector_base(size_t __n, const allocator_type& __a)
      : _M_impl(__a)
      { _M_create_storage(__n); }

我们将得到一个非常大的数字,这使我认为不正确的向量__x以某种方式传递给了复制构造函数。

现在,当将g ++-8与g ++-9的库结合使用时,为什么会发生这种情况,我暂时不知道,我想如果他们需要了解真正的原因,则应该更深入一点。

但是,我想您的主要问题的答案是“问题是由您的编译器和库版本之间的不兼容引起的” :)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++向量std :: bad_alloc错误

程序中的 C++ 向量 std::bad_alloc 错误

C++ - memcpy 给出异常:std::bad_alloc

如何修复“std::bad_alloc”

C ++错误:抛出'std :: bad_alloc'实例后终止调用

C++ 抛出错误“在抛出‘std::bad_alloc’的实例后终止调用”

.. Microsoft C ++的未处理异常:内存位置处的std :: bad_alloc

使用较小内存量时,C ++ std :: bad_alloc错误?

C++:使用向量和迭代器时得到错误:std::bad_alloc

std :: bad_alloc在内存位置0x002b123c

抛出'std::bad_alloc'的实例后调用C++终止

得到错误“抛出'std :: bad_alloc'what():whatstd :: bad_alloc实例后终止调用”

出现错误:抛出'std :: bad :: alloc'what():what std :: bad_alloc实例后终止终止

std :: vector构造函数中的bad_alloc

'new'导致std :: bad_alloc在相对不大的分配上

错误更改/ usr /权限后的'std :: bad_alloc'

TfLearn Confusion Matrix训练在std :: bad_alloc终止

Qt5抛出std :: bad_alloc

将Botan用于PKCS#11的std :: bad_alloc

级联两个向量时的std :: bad_alloc

创建 QQuickWidget 时的 std::bad_alloc 异常

大数据集的dijkstra计算期间的std :: bad_alloc

Std::bad_alloc 在 While 循环中间抛出

如果我得到std :: bad_alloc怎么办?

CPP - 未处理的异常 std::bad_alloc

std::bad_alloc 将文本文件中的单个字符存储到向量 C++ 时

将opencv :: Mat转换为std :: string会得到std :: bad_alloc

为什么std :: exception在std :: bad_alloc之前捕获我的异常?

当我运行我的代码时,我不断收到此错误“在抛出 'std::bad_alloc' what(): std::bad_alloc 实例后调用终止”