c ++ std :: bad_alloc на std :: filesystem :: path append - PullRequest
7 голосов
/ 24 июня 2019

Я испытываю очень странное поведение, которое я перевел к очень простому тесту:

#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

ОБНОВЛЕНИЕ Вот вывод 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)

1 Ответ

2 голосов
/ 25 июня 2019

Я обобщу свои собственные выводы с тем, что другие люди нашли в комментариях.Это не фактический ответ (пока), поскольку в настоящее время я не могу объяснить причину сбоя.

Мне удалось воспроизвести это поведение, установив g ++ - 8 и g ++ - 9 внутри обычного ubuntuОбраз Docker, так что у меня были доступны и /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_base здесь:

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

, мы получим какое-то безумно большое число, что заставляет меня думать, чтоневерный вектор __x был каким-то образом передан конструктору копирования.

Теперь, почему это происходит, когда вы объединяете g ++ - 8 с библиотеками g ++ - 9, я понятия не имею (пока) и я 'Я предполагаю, что нужно идти на один уровень глубже, если им нужно понять истинную причину.

Но я думаю, что ответ на ваш главный вопрос звучит так: «Проблема вызвана несовместимостью версий вашего компилятора и библиотеки»:)

...