使用pthread_create创建线程后使用valgrind测试有内存泄漏(环境Ubuntu 16.04-32bit, 16.04-64bit, 22.04-64bit):
先来看一下这个帖子:
pthread_create()使用detach分离后仍有内存泄漏_tunaG的博客-CSDN博客
测试代码如下:
上面使用两种设置分离线程的方式,属性需不需要销毁(pthread_attr_destroy)对内存没影响,pthread注释或打开相应的代码可以进行测试:
结论如下:
1.不是分离式线程, 不调用pthread_join会有内存泄漏,valgrind显示pthread_create内会调用calloc申请堆内存,应该是在pthread_join中释放;另外pthread_join会阻塞等待对应的子线程结束 。
2.分离式线程调用pthread_join会出错,返回对应的错误值,当然pthread_create申请的内存也不能释放;理论上分离式进程会自己释放内存。
3.上面的内存之所以没有释放,可能是因为线程并未结束进程就直接退出了(这一点不确定,有知道的大佬可以在评论区留下宝贵意见),例如上面的例子,虽然使用pthread_cancel取消了线程,但是pthread_cancel只是发出取消请求,线程是不是响应取消(终止退出)由线程类型和状态决定,何时取消也要看是不是执行到了取消点,默认线程的取消状态是可取消的,类型是延时取消,所以类似上例,取消线程后直接结束进程可能此线程还没来得及响应取消即还没终止,或还没来得及回收资源,所以内存会有泄露。
线程的取消可以参考linux man-pages:
pthread_cancel机翻:
PTHREAD_CANCEL (3) Linux程序员手册 PTHREAD_CANCEL (3)
名字
Pthread_cancel -发送一个取消请求到线程
剧情简介
# include < pthread.h >
Int pthread_cancel(pthread_t线程);
使用-pthread编译和链接。描述函数的作用是:向线程发送一个取消请求。目标线程是否以及何时响应取消请求取决于该线程控制下的两个属性:其可取消性状态和类型。
线程的可取消状态由pthread setcancelstate(3)决定,可以启用(新线程的默认设置)或禁用。如果线程禁用了取消,那么取消请求将保持排队状态,直到线程启用取消。如果线程启用了取消,则其可取消性类型决定何时发生取消。
线程的取消类型由pthread setcanceltype(3)决定,可以是异步的,也可以是延迟的(新线程的默认值)。异步可取消性意味着线程可以在任何时候被取消(通常是立即取消,但系统不能保证这一点)。延迟可取消性意味着取消将被延迟,直到线程下一次调用作为取消点的函数。在pthreads(7)中提供了一个函数列表,这些函数是或可能是取消点。
当一个取消请求被执行时,线程将执行以下步骤(按此顺序):
1. 取消清理处理程序被弹出(与它们被推送的顺序相反)并被调用。(见pthread_cleanup_push(3))。
2. 特定于线程的数据析构函数以未指定的顺序被调用。(见pthread_key_create(3))。
3.线程终止。(见pthread_exit(3)。)
上述步骤是相对于pthread_cancel()调用异步发生的;pthread cancel()的返回状态仅仅通知调用者取消请求是否成功排队。
在被取消的线程终止后,使用pthread_join(3)与该线程的连接将获得PTHREAD_CANCELED作为线程的退出状态。(与线程连接是知道取消已经完成的唯一方法。)
返回值
如果成功,pthread_cancel()返回θ;当出现错误时,它返回一个非零的错误编号。
错误
ESRCH 找不到ID为thread的线程。
pthread_setcancelstate 和 pthread_setcanceltype
机翻:
PTHREAD_SETCANCELSTATE (3)Linux程序员手册PTHREAD_SETCANCELSTATE (3)
名字
Pthread_setcancelstate、pthread_setcanceltype 设置可取消性的状态和类型
剧情简介
# include < pthread.h >
Int pthread_setcancelstate(Int state, Int *oldstate);
Int pthread_setcanceltype(Int类型,Int *oldtype);
使用-pthread编译和链接。
描述
pthread_setcancelstate()将调用线程的可取消状态设置为state中给定的值。线程先前的可取消状态在oldstate所指向的缓冲区中返回。state参数必须具有以下值之一:
PTHREAD_CANCEL_ENABLE线程是可取消的。这是所有新线程(包括初始线程)的默认可取消状态。线程的可取消性类型决定了可取消线程何时响应取消请求。
PTHREAD_CANCEL_DISABLE该线程不可取消。如果收到取消请求,它将被阻塞,直到启用可取消性。
pthread_setcanceltype()将调用线程的可取消性type设置为type中给定的值。线程的先前可取消类型在oldtype所指向的缓冲区中返回。类型参数必须具有以下值之一:
PTHREAD_CANCEL_DEFERRED:取消请求被延迟,直到线程下一次调用作为取消点的函数(参见pthreads(7))。这是所有新线程(包括初始线程)的默认可取消类型。
PTHREAD_CANCEL_ASYNCHRONOUS :线程可以在任何时候被取消。(通常,它将在收到取消请求后立即取消,但系统不能保证这一点。)这些函数中的每个函数执行的set-and-get操作相对于调用同一函数的进程中的其他线程来说是原子性的。
返回值
如果成功,这些函数返回0;当出现错误时,它们返回一个非零的错误编号。
错误
pthread_setcancelstate()可能会失败,并出现以下错误: EINVAL状态值无效。
pthread_setcanceltype()可能会失败,并出现以下错误: EINVAL类型无效值。