Прежде всего, эта проблема связана с совместным использованием clang (любой версии) и libstdc ++ версии 6.5.0.
Я использую следующую идиому в моей базе кода, чтобы скрыть реализацию отпользователь:
#include <memory>
class myclass : public std::enable_shared_from_this<myclass> {
class impl;
protected:
myclass() = default;
public:
myclass(myclass&&) = delete;
myclass(myclass const&) = delete;
myclass& operator=(myclass&&) = delete;
myclass& operator=(myclass const&) = delete;
virtual ~myclass() = default;
static std::shared_ptr<myclass> create();
int get();
};
class myclass::impl : public myclass {
public:
using myclass::myclass;
int get_impl() {
return 33;
}
};
std::shared_ptr<myclass> myclass::create() {
return std::make_shared<impl>();
}
int myclass::get() {
return static_cast<impl*>(this)->get_impl();
}
int main() {
auto ref = myclass::create();
return ref->shared_from_this()->get();
}
Идиома использует закрытый класс, который наследует и реализует публичный базовый класс.При запуске этого сниппета в Ubuntu 18.04 с использованием clang++ -O3 -std=c++11 main.cpp && ./a.out
сниппет со следующим выводом:
terminate called after throwing an instance of 'std::bad_weak_ptr'
what(): bad_weak_ptr
со следующей обратной трассировкой:
#0 0x00007ffa76a7de97 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffa76a7f801 in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffa774728fb in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffa77478d3a in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffa77478d95 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffa77478fe8 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x0000000000404f7c in std::__throw_bad_weak_ptr() ()
#7 0x0000000000404e92 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__weak_count<(__gnu_cxx::_Lock_policy)2> const&) ()
#8 0x0000000000404e2f in std::__shared_ptr<myclass, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<myclass, void>(std::__weak_ptr<myclass, (__gnu_cxx::_Lock_policy)2> const&) ()
#9 0x0000000000404df8 in std::shared_ptr<myclass>::shared_ptr<myclass, void>(std::weak_ptr<myclass> const&) ()
#10 0x0000000000403d2c in std::enable_shared_from_this<myclass>::shared_from_this() ()
#11 0x0000000000403ac8 in main ()
Тестовая платформа запускает следующий компилятор истандартная библиотека:
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0
Хотя этот код отлично работает на других платформах и / или компиляторах:
- GCC 7.3.0 и "lib / gcc / x86_64-linux-gnu /7.3.0 "работает на той же платформе
- Clang 3.8.0 и" lib / gcc / x86_64-linux-gnu / 6.5.0 "работает на другой платформе
- Clang 7.0.1 и«lib / gcc / x86_64-linux-gnu / 6.5.0» работает на другой платформе
- Windows MSVC 15.9.4
В целом, похоже, что наследование от std::shared_from_this
отсутствуетstd::make_shared
не обнаруживается при наследовании его от родительского класса в libstdc ++ выше версии 6.5.0 при использовании любой версии clang.
Можно ли обойти эту проблему, сохраняя идиому?
Что может быть причиной дефекта здесь?Следует ли об этом сообщать любому багтрекеру (но какой из них наиболее подходящий, поскольку это кажется проблемой совместимости между clang и libstdc ++).