【问题解决】C++调用shared_from_this()报错bad_weak_ptr解决方案
一、问题背景
在 C++11 之前,通常使用 std::shared_ptr
来管理对象的生命周期,但如果一个对象需要在内部获取指向自身的 shared_ptr
,就比较麻烦。直接构造一个 shared_ptr
会导致引用计数不正确,从而引发内存泄漏或悬空指针的问题。
因此,C++11 引入了 std::enable_shared_from_this
,它提供了一种安全且高效的方式,让一个对象能够在内部获取指向自身的 shared_ptr
。
通过继承 std::enable_shared_from_this
,类可以调用 shared_from_this()
函数来获取指向自身的 shared_ptr
。这个函数会保证 shared_ptr
的引用计数是正确的,避免了手动管理引用计数的复杂性。
二、正常情况
正常情况下,在Test
函数中使用shared_from_this();
,编译执行成功,可以捕获符合生命周期的this指针。
#include <memory>
class Node : public std::enable_shared_from_this<Node> {
public:
Node() {}
~Node() {}
void Test() {
auto sharedThis = shared_from_this();
}
};
int main() {
std::shared_ptr<Node> node1 = std::make_shared<Node>();
node1->Test();
return 0;
}
三、异常情况
- 构造函数中调用
shared_from_this()
#include <memory>
class Node : public std::enable_shared_from_this<Node> {
public:
Node() {
auto sharedThis = shared_from_this();
}
~Node() {}
void Test() {}
};
int main() {
std::shared_ptr<Node> node1 = std::make_shared<Node>();
node1->Test();
return 0;
}
- 非
unique_ptr
构造enable_shared_from_this
对象
#include <memory>
class Node : public std::enable_shared_from_this<Node> {
public:
Node() {}
~Node() {}
void Test() {
auto sharedThis = shared_from_this();
}
};
int main() {
std::unique_ptr<Node> node1 = std::make_unique<Node>();
node1->Test();
return 0;
}
- 裸指针构造
enable_shared_from_this
对象
#include <memory>
class Node : public std::enable_shared_from_this<Node> {
public:
Node() {}
~Node() {}
void Test() {
auto sharedThis = shared_from_this();
}
};
int main() {
Node* node1 = new Node();
node1->Test();
return 0;
}
以上三种情况都能编译成功,但执行时报错:
terminate called after throwing an instance of 'std::bad_weak_ptr'
what(): bad_weak_ptr
Aborted (core dumped)
四、异常分析
-
查看c++ reference中
std::bad_weak_ptr
的描述:当shared_ptr
指向一个已经被删除的对象时会抛出std::bad_weak_ptr
异常。std::bad_weak_ptr
is the type of the object thrown as exceptions by the constructors of std::shared_ptr that take std::shared_ptr as the argument, when the std::shared_ptr refers to an already deleted object. -
查看
shared_ptr.h
头文件中的shared_from_this()
源码和_M_weak_this
定义。
public:
shared_ptr<_Tp>
shared_from_this()
{ return shared_ptr<_Tp>(this->_M_weak_this); }
shared_ptr<const _Tp>
shared_from_this() const
{ return shared_ptr<const _Tp>(this->_M_weak_this); }
mutable weak_ptr<_Tp> _M_weak_this;
-
发现
shared_from_this()
实现就是将一个weak_ptr
的this指针转换成shared_ptr
指针的过程。 -
构造函数中调用
shared_from_this()
时,Node实例还未被构造,_M_weak_this
还未生成,所以报错bad_weak_ptr
。 -
非
unique_ptr
构造enable_shared_from_this
对象和裸指针构造enable_shared_from_this
对象都不被std::shared_ptr
管理,当调用shared_from_this()
时,将导致未定义行为。
五、解决方案
- 对于构造函数中调用
shared_from_this()
的情况,应该避免在构造函数中调用shared_from_this()
,解决办法即将相关逻辑移到函数中执行,在构造完成后调用相应函数以实现相同逻辑。 - 对于非
unique_ptr
构造enable_shared_from_this
对象和裸指针构造enable_shared_from_this
对象的情况,应使用std::make_shared
或std::shared_ptr
实现相关函数的构造,使构造出的对象受std::shared_ptr
管理。
六、参考文档
- C++ reference之std::bad_weak_ptr:https://en.cppreference.com/w/cpp/memory/bad_weak_ptr。
- C++源码之
shared_ptr.h
头文件。