C++编程指南21-线程detach后其注意变量的生命周期
- 创业
- 2025-09-17 06:03:03

一:概述
如果一个线程被 detach() 了,那么它的生命周期将独立于创建它的作用域。因此,该线程只能安全地访问:
全局变量(global/static objects)堆上分配的对象(free-store allocated objects,即 new / make_unique() 创建的对象) 其他作用域的对象可能会在线程访问它们之前被销毁,导致 悬空指针(dangling pointer) 和 未定义行为。 二:示例代码下面以一段代码来介绍下前面说的这种情况:
#include <iostream> #include <thread> #include <memory> void f(int* p) { *p = 99; // 可能访问悬空指针 } int glob = 33; // 全局变量 void some_fct(int* p) { int x = 77; std::thread t0(f, &x); // 错误!x 是局部变量 std::thread t1(f, p); // 错误!p 可能指向局部变量 std::thread t2(f, &glob); // OK!glob 是全局变量 auto q = std::make_unique<int>(99); std::thread t3(f, q.get()); // 错误!q 在 some_fct 结束时销毁 t0.detach(); t1.detach(); t2.detach(); t3.detach(); }在这段代码中,线程detach后,会有以下几种情况发生:
t0(f, &x); 和 t1(f, p);
x 是 some_fct() 的局部变量,p 可能指向局部变量。t0 和 t1 可能会在 some_fct() 结束后访问已销毁的变量,导致 未定义行为。t3(f, q.get());
q 是 make_unique<int>(99) 创建的智能指针,q.get() 获取的指针在 some_fct() 结束时无效。std::unique_ptr 在函数返回时析构,导致 t3 访问无效内存。t2(f, &glob);
由于 glob 是全局变量,它的生命周期足够长,可以安全地被 t2 访问。 三:解决方案如何避免线程detach后的空悬指针和未定义行为?有以下两种方案:
1. 只使用全局变量或堆分配的对象
#include <iostream> #include <thread> #include <memory> void f(int* p) { *p = 99; } int glob = 33; void some_fct(int* p) { auto q = new int(99); // 使用堆对象 std::thread t1(f, &glob); // OK,全局变量 std::thread t2(f, q); // OK,堆上分配的对象 t1.detach(); t2.detach(); // 需要手动释放 q,避免内存泄漏 delete q; }2. 避免 detach(),使用 std::thread::join() 或 joining_thread
void some_fct() { int x = 77; std::thread t(f, &x); // OK,因为 t.join() 之前 x 一直有效 t.join(); // 等待线程结束,确保不会访问销毁的对象 } class joining_thread { std::thread t; public: template <typename... Args> explicit joining_thread(Args&&... args) : t(std::forward<Args>(args)...) {} ~joining_thread() { if (t.joinable()) { t.join(); } } }; void some_fct() { int x = 77; joining_thread t(f, &x); // OK }C++编程指南21-线程detach后其注意变量的生命周期由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“C++编程指南21-线程detach后其注意变量的生命周期”