weak_ptr引起的资源泄露问题

weak_ptr引起的资源泄露问题和join问题 Resource deadlock avoided

问题描述

在项目开发过程中涉及到许多类间的包含与嵌套包含关系,类里面又启动了多个线程,出现偶现coredump问题:
terminate called after throwing an instance of ‘std::system_error’
what(): Resource deadlock avoided

问题复现

将项目中的问题抽象为A包含数据成员B(直接包含或者间接包含),B又反过来持有的A的weak_ptr,B中开启线程会持续调用A,代码如下:

#include <iostream>
#include <thread>
#include <functional>

using namespace std;

class TopObject;

class BottlemObject {
public:
    BottlemObject(std::weak_ptr<TopObject> obj) : top_obj_(obj) {
        thread_ = std::thread(&BottlemObject::Func, this);
        std::cout << "BottlemObject construct!" << std::endl;
    }
    ~BottlemObject() {
        is_stop = true;
        if(thread_.joinable()) {
            thread_.join();
        }
        std::cout << "BottlemObject destruct!" << std::endl;
    }
private:
    void Func() {
        while(!is_stop) {
            auto obj = top_obj_.lock();
            if(!obj) { return; }
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

private:
    std::weak_ptr<TopObject> top_obj_;
    bool is_stop{false};
    std::thread thread_;
};


class TopObject : public std::enable_shared_from_this<TopObject> {
public:
    TopObject() {
        std::cout << "TopObject construct!" << std::endl;
    }
    void CreateObj() {
        bot_obj_ = std::make_shared<BottlemObject>(weak_from_this());
    }
    ~TopObject() { std::cout << "TopObject destruct!" << std::endl;}

private:
    std::shared_ptr<BottlemObject> bot_obj_;
};

class Defer {
public:
    Defer(std::function<void()> func) : func_(func) {}
    ~Defer() { func_(); }
private:
    std::function<void()> func_;
};

int main() {
    {
        auto obj = std::make_shared<TopObject>();
        obj->CreateObj();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    //这里主线程卡住2s,保证func()退出循环调用到join
    std::this_thread::sleep_for(std::chrono::seconds(2));
    Defer defer([]{std::cout << "main exit!!!" << std::endl;});
    return 0;
}

执行结果如下:

问题分析

执行流程如下:
1、进程启动,创建TopObject对象
2、TopObject创建BottlemObject对象,BottlemObject对象持有了TopObject的weak_ptr,启动thread_并且调用Func(),Func中循环lock出TopObject的shared_ptr,持有1s
3、main中{}块退出,TopObject的shared_ptr引用计数-1,之后仅有BottlemObject对象的thread持有shared_ptr
4、BottlemObject对象的Func()退出第一次循环,TopObject对象开始析构,继续调用BottlemObject对象析构函数,接着调用thread join自身触发了coredump

解决办法

以上问题的根本原因是TopObject对象被自身创建的线程对象持有,这样其作用域结束后无法正常析构,造成资源泄露。
解决办法是,将BottlemObject的top_obj_改为TopObject*,这样在{}块结束时,会调用TopObject的析构函数,调用BottlemObject的析构,调用thread_的join(),待Func执行完以后,BottlemObject析构完成退出,TopObject析构完成退出,然后进程退出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值