std::bad_weak_ptr 从基础 class 继承 std::shared_from_this 时
std::bad_weak_ptr when inheriting std::shared_from_this from base class
首先这个问题似乎与同时使用clang(任何版本)和高于6.5.0版本的libstdc++有关。
我在我的代码库中使用以下习惯用法来对用户隐藏实现:
#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();
}
该成语使用私有class继承并实现了public基础class。
当 运行 此代码段在 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
尽管此代码在其他平台上运行良好and/or编译器:
- 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
总体而言,当使用任何 clang 时,在高于 6.5.0 版的 libstdc++ 中从父 class 继承时,std::shared_from_this
似乎未检测到继承版本。
是否可以在保留习语的同时解决这个问题?
什么可能导致这里的缺陷?
这是否应该报告给任何错误跟踪器(但哪个是正确的,因为这似乎是 clang 和 libstdc++ 之间的互操作性问题)。
正如您已经提到的,问题确实似乎是 std::shared_ptr
没有检测到 std::enable_shared_from_this
基 class。一种适用于我的机器的解决方法:
std::shared_ptr<myclass> myclass::create() {
return std::shared_ptr<myclass>{static_cast<myclass*>(new impl{})};
}
至于在哪里报告错误:我会在 llvm bugtracker 上报告它,毕竟它可以与 GCC 一起使用,并且与 GCC 库兼容符合 clangs 的利益。
首先这个问题似乎与同时使用clang(任何版本)和高于6.5.0版本的libstdc++有关。
我在我的代码库中使用以下习惯用法来对用户隐藏实现:
#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();
}
该成语使用私有class继承并实现了public基础class。
当 运行 此代码段在 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
尽管此代码在其他平台上运行良好and/or编译器:
- 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
总体而言,当使用任何 clang 时,在高于 6.5.0 版的 libstdc++ 中从父 class 继承时,std::shared_from_this
似乎未检测到继承版本。
是否可以在保留习语的同时解决这个问题?
什么可能导致这里的缺陷? 这是否应该报告给任何错误跟踪器(但哪个是正确的,因为这似乎是 clang 和 libstdc++ 之间的互操作性问题)。
正如您已经提到的,问题确实似乎是 std::shared_ptr
没有检测到 std::enable_shared_from_this
基 class。一种适用于我的机器的解决方法:
std::shared_ptr<myclass> myclass::create() {
return std::shared_ptr<myclass>{static_cast<myclass*>(new impl{})};
}
至于在哪里报告错误:我会在 llvm bugtracker 上报告它,毕竟它可以与 GCC 一起使用,并且与 GCC 库兼容符合 clangs 的利益。