如何正确释放堆分配的std::thread*内存?示例代码是否存在内存泄漏?
代码问题分析与解答
是否会产生内存泄漏
一定会产生内存泄漏,且每次调用StartThread创建线程成功就会泄漏一次,循环10次调用的话最多会泄漏10份std::thread对象的堆内存,原因如下:
- 你通过
new std::thread在堆上分配了线程对象,地址存入成员变量m_pThread后,没有执行任何释放操作,就直接执行m_pThread = nullptr将指针置空,直接丢失了堆内存的唯一引用,这块内存再也没有机会被回收。 - 除内存泄漏外,该代码还存在额外风险:
std::thread对象如果处于可结合(joinable)状态时被析构,会直接触发std::terminate导致程序崩溃,你当前的实现没有对线程对象执行join(等待线程结束)或者detach(分离线程所有权)操作,还存在程序崩溃的隐患。
堆分配std::thread的正确释放方式
正确的释放需要遵循「先处理线程状态,再释放内存」的原则,具体实践方案如下:
基础方案(使用裸指针)
- 不要随意清空存储线程地址的指针,必须保留指针直到资源释放
- 释放前先判断线程是否可结合,根据业务需求选择调用
join()等待线程执行完成,或者调用detach()将线程和对象分离 - 处理完线程状态后调用
delete释放指针对象 - 在类的析构函数中统一兜底清理线程资源,避免类实例销毁时泄漏资源
修正后的代码示例:
// 类的析构函数补充资源清理逻辑 A::~A() { if (m_pThread != nullptr) { if (m_pThread->joinable()) { m_pThread->join(); // 业务不需要等待的话也可以用detach } delete m_pThread; m_pThread = nullptr; } } bool A::StartThread() { bool mThreadSuccess = false; try { // 先清理之前可能存在的旧线程资源,避免覆盖指针导致泄漏 if (m_pThread != nullptr) { if (m_pThread->joinable()) { m_pThread->join(); } delete m_pThread; m_pThread = nullptr; } m_pThread = new std::thread(&A::DisableThread, this); mThreadSuccess = true; } catch (...) { m_pDisable = false; } // 移除原有的错误置空指针逻辑 return mThreadSuccess; }
更安全的方案(使用智能指针)
不需要手动管理内存释放,直接用std::unique_ptr自动管理线程对象的生命周期:
- 类成员声明改为:
std::unique_ptr<std::thread> m_pThread;
- 释放资源时只需要处理线程状态,不需要手动
delete,智能指针会自动在生命周期结束时回收内存:
// 重置线程资源的逻辑示例 if (m_pThread && m_pThread->joinable()) { m_pThread->join(); } m_pThread.reset(); // 自动释放旧的线程对象内存
内容的提问来源于stack exchange,提问作者DecryptDcode
相关产品推荐
相关产品推荐

