UWP环境下含concurrency::task的C++类析构函数未执行原因咨询
析构函数未执行的原因及解决方案
兄弟,我太懂你这种遇到析构函数不执行的焦虑了——毕竟没执行就意味着你写的任务清理代码根本没跑,内存泄漏的风险确实存在。结合你用的concurrency::task和cancellation_token_source,大概率是下面这些原因导致的:
可能的原因
- 循环引用锁死了对象回收:如果你的
m_task在执行逻辑里捕获了this指针(比如lambda里用this访问成员),而concurrency::task底层会持有任务实例直到它完成,这就形成了循环依赖:MyClass对象持有m_task,m_task又持有MyClass的引用。这种情况下,即使外部没有其他引用,对象的引用计数也降不到0,析构函数自然不会触发。 - 任务一直处于活跃状态:如果
Start方法启动的是无限循环任务(比如每隔interval重复执行,没有终止条件),且你从未调用cancellation_token的cancel()方法,那么m_task会一直处于运行状态。部分并发框架会让活跃任务持有关联对象的引用,防止对象被提前销毁,这也会导致析构函数无法执行。 - 外部存在未释放的引用:可能你在其他地方(比如全局容器、其他类成员)还持有
MyClass对象的指针/引用,导致对象无法被销毁。
解决方法
1. 打破循环引用
如果任务里需要访问MyClass成员,改用弱引用捕获,避免强引用锁死对象。比如让MyClass继承std::enable_shared_from_this:
class MyClass : public std::enable_shared_from_this<MyClass> { public: explicit MyClass(MyException func); ~MyClass(); void Start(int interval = 2000); private: concurrency::task<void> m_task; concurrency::cancellation_token_source m_cancellationToken; // 其他成员 }; void MyClass::Start(int interval) { auto weak_this = weak_from_this(); m_task = concurrency::create_task([this, weak_this, interval]() { while (!m_cancellationToken.get_token().is_canceled()) { auto strong_this = weak_this.lock(); if (!strong_this) { break; // 对象已销毁,退出任务循环 } // 执行你的任务逻辑 concurrency::wait(interval); } }); }
这样任务持有的是弱引用,不会阻止对象被销毁,当对象要回收时,weak_this.lock()会返回空,任务自动退出。
2. 主动停止任务并等待完成
在析构函数执行前,先主动取消任务并等待它结束。可以新增一个停止方法,在释放对象前调用:
class MyClass { public: explicit MyClass(MyException func); ~MyClass(); void Start(int interval = 2000); void StopAndWait(); // 新增停止方法 private: concurrency::task<void> m_task; concurrency::cancellation_token_source m_cancellationToken; std::mutex m_mutex; // 保证线程安全 // 其他成员 }; void MyClass::StopAndWait() { std::lock_guard<std::mutex> lock(m_mutex); if (!m_cancellationToken.get_token().is_canceled()) { m_cancellationToken.cancel(); m_task.wait(); // 等待任务彻底完成 } } MyClass::~MyClass() { StopAndWait(); // 其他清理逻辑 }
使用时先调用停止方法再释放对象:
auto my_obj = std::make_unique<MyClass>(...); my_obj->Start(); // 不需要对象时 my_obj->StopAndWait(); my_obj.reset(); // 此时析构函数会正常执行
3. 检查外部引用
排查代码中所有使用MyClass对象的地方,确保没有遗漏的全局容器、静态变量或者其他类成员持有该对象的引用,这些都会阻止对象被销毁。
内容的提问来源于stack exchange,提问作者sohel14_cse_ju
相关产品推荐
相关产品推荐

