引用计数智能指针自引用循环导致内存泄漏问题求解
问题核心
当前实现的ref是强引用智能指针,持有对象时会递增引用计数。对象内部持有自身强引用时,外部所有引用释放后,对象引用计数仍为1,无法触发析构,属于自引用类型的循环引用问题。
解决方案
方案1:拆分强/弱引用类型(最通用,推荐优先使用)
额外实现不增加引用计数的弱引用智能指针weak_ref:
- 弱引用仅持有对象观测权,不会阻止对象销毁
- 访问对象前调用
weak_ref的lock()方法尝试升级为强引用ref,升级成功则对象存活可正常访问,升级失败说明对象已销毁 - 原有示例仅需将内部成员
m_ref类型从ref<Object>改为weak_ref<Object>即可,自引用不会增加引用计数,外部引用释放后对象会正常析构
改后代码示例:
class Derived : public Object { public: static ref<Object> Create() { return ref<Object>(new Derived()); } private: Derived() : m_ref(this) // 弱引用赋值不会增加引用计数 { // 访问对象前先升级为强引用 if (ref<Object> strong_ref = m_ref.lock()) { // 正常访问对象逻辑 } } weak_ref<Object> m_ref; };
方案2:实现enable_ref_from_this机制(适用于需要持有自身强引用的场景)
如果业务确实需要对象内部持有自身强引用(比如异步回调要保证执行时对象存活),给基类Object新增继承enable_ref_from_this辅助类:
- 辅助类内部默认存储指向当前对象的弱引用
- 对外提供
ref_from_this()方法,调用时将内部弱引用升级为强引用返回 - 要求对象必须通过
ref智能指针托管,禁止栈上创建、禁止直接使用裸指针,你现有的Create工厂方法符合使用要求
改后代码示例:
// 基类新增继承辅助类 class Object : public enable_ref_from_this<Object> { // 原有基类逻辑不变 }; class Derived : public Object { public: static ref<Object> Create() { auto obj = ref<Object>(new Derived()); // 构造完成后通过ref_from_this获取自身强引用赋值 obj->m_ref = obj->ref_from_this(); return obj; } private: Derived() = default; ref<Object> m_ref; };
方案3:手动断环(兜底方案,不推荐)
如果不想改动现有智能指针实现,给Object基类新增dispose接口,派生类实现接口时主动将内部持有的所有强引用置空,断开循环引用环。需要销毁对象前主动调用dispose方法即可。该方案依赖手动调用,遗漏就会出现内存泄漏,仅适合临时修复场景。
内容的提问来源于stack exchange,提问作者DeltaJuliet2k
相关产品推荐
相关产品推荐

