You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:26:19