代码编织梦想


在这里插入图片描述

1. 目的

线程泄漏是使用多线程时容易出现的一个错误, 这和内存泄漏有点像:操作系统为创建过程消耗了资源,但没有回收, 如果频繁的创建那么系统被严重拖累, 新申请线程或内存的成功概率降低。

2. 什么是线程泄漏

使用 pthread 实现多线程任务调度时, 子线程是从主线程创建的, 如下两种情况都满足时,会产生线程泄漏:

  • 子线程执行的函数中没有显式的销毁子线程 (未执行 pthread_detach()
  • 主线程中也没有等待子线程的结束 (未执行 pthread_join()

3. pthread 线程泄漏例子

3.1 代码

这里简单起见, 线程函数 f() 采用极简方式设定:传空指针参数, 只打印一句话和返回空指针。

// 这是一个反面例子。

#include <cstddef>
#include <pthread.h>
#include <stdio.h>

void* f(void*)
{
    printf("Hello from thread function f\n");
    return NULL;
}

int main()
{
    pthread_t t;
    pthread_create(&t, NULL, f, NULL); // 主线程里开启子线程 t
    printf("This is main thread\n");

    return 0;
}

3.2 编译和运行

zz@Legion-R7000P% clang++ leak_example.cpp

第一次运行

zz@Legion-R7000P% ./a.out 
Hello from thread function f
This is main thread

第二次运行

zz@Legion-R7000P% ./a.out
This is main thread

3.3 简要分析

由于主线程(main()函数)没有等待子线程的结束, 程序运行可能出现的情况有两种:

  • 打印了子线程的内容
  • 没打印子线程的内容

以上两种结果都可能出现, 不能认为能出现正确结果就万事大吉了, 需要严格确保结果的正确性。

4. 检测线程泄漏

使用 ThreadSanitizer 可以检查 Pthread 的内存泄漏。需要的步骤如下

4.1 编译链接时传入参数 -fsanitize=thread

clang++ leak_example.cpp -fsanitize=thread

4.2 确认 TSAN_OPTIONS 环境变量

第一种: TSAN_OPTIONS 环境变量为空。
第二种: 设定为检测线程泄漏: export TSAN_OPTIONS="report_thread_leaks=1"

以上两种情况,都可以让线程泄漏的问题在程序运行阶段被报告出来。
而如果设定了 export TSAN_OPTIONS="report_thread_leaks=0", 则无法报告线程泄漏问题。

5. 修复线程泄漏

5.1 方法1: 主线程等待子线程

#include <cstddef>
#include <pthread.h>
#include <stdio.h>

void* f(void*)
{
    printf("Hello from thread function f\n");
    return NULL;
}

int main()
{
    pthread_t t;
    pthread_create(&t, NULL, f, NULL); // 主线程里开启子线程 t

    pthread_join(t, NULL); // 主线程等待子线程 t 的结束

    return 0;
}

5.2 方法2:子线程主动脱离主线程

用到了 pthread_detach() 这个 API:

在这里插入图片描述
应用到代码中:

#include <cstddef>
#include <pthread.h>
#include <stdio.h>

void* f(void*)
{
    pthread_detach(pthread_self()); // 子线程主动 detach
    printf("Hello from thread function f\n");
    return NULL;
}

int main()
{
    pthread_t t;
    pthread_create(&t, NULL, f, NULL); // 主线程里开启子线程 t

    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/baiyu33/article/details/130837694

C++多线程一:pThread-爱代码爱编程

https://www.runoob.com/cplusplus/cpp-multithreading.html 1.创建线程 下面的程序,我们可以用它来创建一个 POSIX 线程: #include <pthread.h> pthread_create (myThread, attr, start_routine, arg) 在这里

Pthread多线程入门学习笔记-爱代码爱编程

文章目录 前言线程创建案例案例解析JoiningJoining的一般过程案例案例解析Stack Management案例其它函数Mutex Variable(互斥锁)Creating and Destroying Mutexes and Its AttributesLocking and Unlocking MutexesCondition Var

C++ pthread 多线程-爱代码爱编程

本篇是我在学习C++多线程的时候做的笔记,主要记录的是基础的流程,部分代码实例,以及重点函数的说明。 pthread 入口函数类型说明 void * func1(void * t) void* 表示无类型指针 void*作为函数参数,表示函数接收一个指针,不管是什么类型的指针都可以,但是传递之前要强制转换为无类型指针。 基础流程 pthread_

linux 线程 虚拟内存,关于pthread多线程虚拟内存的有关问题-爱代码爱编程

关于pthread多线程虚拟内存的问题 本帖最后由 jack_leiwin 于 2014-06-12 16:11:20 编辑 各位前辈,你们好 我写了一个小程序,代码如下 #include #include #include using namespace std; pthread_mutex_t fmx; void* func(vo

linux 多线程原理深剖_线程的布局_乔乔家的龙龙的博客-爱代码爱编程

目录 传统艺能😎Linux 线程🤔phread🤔 二级页表🤔线程优点🤔线程缺点🤔线程异常🤔进程与线程🤔多线程共享🤔Linux线程控制🤔POSIX线程库😋 线程的创建😋获取线程id😎 线程