正确使用pthread_create,防止内存泄漏
近日,听说pthread_create会造成内存泄漏,觉得不可思议,因此对posix(nptl)的线程创建和销毁进行了分析。
点击(此处)折叠或打开
- int
- __pthread_create_2_1 (newthread, attr, start_routine, arg)
- pthread_t *newthread;
- const pthread_attr_t *attr;
- void *(*start_routine) (void *);
- void *arg;
- {
- STACK_VARIABLES;
- const struct pthread_attr *iattr = (struct pthread_attr *) attr;
- if (iattr == NULL)
- /* Is this the best idea? On NUMA machines this could mean
- accessing far-away memory. */
- iattr = &default_attr;
- struct pthread *pd = NULL;
- int err = ALLOCATE_STACK (iattr, &pd);//为tcb分配内存
- if (__builtin_expect (err != 0, 0))
- /* Something went wrong. Maybe a parameter of the attributes is
- invalid or we could not allocate memory. */
- return err;
- //……
- err = create_thread (pd, iattr, STACK_VARIABLES_ARGS);//正式创建线程
2.查看createthread.c(nptl/sysdeps/pthread/createthread.c)
点击(此处)折叠或打开
- static int
- create_thread (struct pthread *pd, const struct pthread_attr *attr,
- STACK_VARIABLES_PARMS)
- {
- #ifdef TLS_TCB_AT_TP
- assert (pd->header.tcb != NULL);
- #endif
- //……
- int res = do_clone (pd, attr, clone_flags, start_thread,
- STACK_VARIABLES_ARGS, 1);//clone一个进程
3.接着看start_thread(nptl/pthread_create.c)做了什么
点击(此处)折叠或打开
- static int
- start_thread (void *arg)
- {
- struct pthread *pd = (struct pthread *) arg;
- //……
- /* Run the code the user provided. */
- #ifdef CALL_THREAD_FCT
- THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd));
- #else
- THREAD_SETMEM (pd, result, pd->start_routine (pd->arg)); //正式启动线程的执行,并等待执行完成
- #endif
- //……
- if (IS_DETACHED (pd))
- /* Free the TCB. */
- __free_tcb (pd);//如果设置detached标志,则释放tcb占用的内容,否则直接返回
- else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0))
- {
- /* Some other thread might call any of the setXid functions and expect
- us to reply. In this case wait until we did that. */
- do
- lll_futex_wait (&pd->setxid_futex, 0, LLL_PRIVATE);
- while (pd->cancelhandling & SETXID_BITMASK);
- /* Reset the value so that the stack can be reused. */
- pd->setxid_futex = 0;
- }
从上面的过程,我们可以看到,如果在创建线程的时候,如果没有设置detached标志,则tcb内存永远不会释放
点击(此处)折叠或打开
- int
- pthread_detach (th)
- pthread_t th;
- {
- struct pthread *pd = (struct pthread *) th;
- /* Make sure the descriptor is valid. */
- if (INVALID_NOT_TERMINATED_TD_P (pd))
- /* Not a valid thread handle. */
- return ESRCH;
- int result = 0;
- /* Mark the thread as detached. */
- if (atomic_compare_and_exchange_bool_acq (&pd->joinid, pd, NULL))
- {
- /* There are two possibilities here. First, the thread might
- already be detached. In this case we return EINVAL.
- Otherwise there might already be a waiter. The standard does
- not mention what happens in this case. */
- if (IS_DETACHED (pd))
- result = EINVAL;
- }
- else
- /* Check whether the thread terminated meanwhile. In this case we
- will just free the TCB. */
- if ((pd->cancelhandling & EXITING_BITMASK) != 0)
- /* Note that the code in __free_tcb makes sure each thread
- control block is freed only once. */
- __free_tcb (pd);//经过一系列的容错判断,直接释放tcb占用的内存
- return result;
- }
最后,我们看一下pthread_join(nptl/pthread_join.c)做了什么
点击(此处)折叠或打开
- int
- pthread_join (threadid, thread_return)
- pthread_t threadid;
- void **thread_return;
- {
- struct pthread *pd = (struct pthread *) threadid;
- /* Make sure the descriptor is valid. */
- if (INVALID_NOT_TERMINATED_TD_P (pd))
- /* Not a valid thread handle. */
- return ESRCH;
- /* Is the thread joinable?. */
- if (IS_DETACHED (pd))
- /* We cannot wait for the thread. */
- return EINVAL;
- struct pthread *self = THREAD_SELF;
- int result = 0;
- /* During the wait we change to asynchronous cancellation. If we
- are canceled the thread we are waiting for must be marked as
- un-wait-ed for again. */
- pthread_cleanup_push (cleanup, &pd->joinid);
- /* Switch to asynchronous cancellation. */
- int oldtype = CANCEL_ASYNC ();
- if ((pd == self
- || (self->joinid == pd
- && (pd->cancelhandling
- & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
- | TERMINATED_BITMASK)) == 0))
- && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
- /* This is a deadlock situation. The threads are waiting for each
- other to finish. Note that this is a "may" error. To be 100%
- sure we catch this error we would have to lock the data
- structures but it is not necessary. In the unlikely case that
- two threads are really caught in this situation they will
- deadlock. It is the programmer's problem to figure this
- out. */
- result = EDEADLK;
- /* Wait for the thread to finish. If it is already locked something
- is wrong. There can only be one waiter. */
- else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
- self,
- NULL), 0))
- /* There is already somebody waiting for the thread. */
- result = EINVAL;
- else
- /* Wait for the child. */
- lll_wait_tid (pd->tid);
- /* Restore cancellation mode. */
- CANCEL_RESET (oldtype);
- /* Remove the handler. */
- pthread_cleanup_pop (0);
- if (__builtin_expect (result == 0, 1))
- {
- /* We mark the thread as terminated and as joined. */
- pd->tid = -1;
- /* Store the return value if the caller is interested. */
- if (thread_return != NULL)
- *thread_return = pd->result;//设置返回值
- /* Free the TCB. */
- __free_tcb (pd);/释放TCB占用内存
- }
- return result;
- }
点击(此处)折叠或打开
- void run() {
- return;
- }
- int main(){
- pthread_t thread;
- pthread_attr_t attr;
- pthread_attr_init( &attr );
- pthread_attr_setdetachstate(&attr,1);
- pthread_create(&thread, &attr, run, 0);
- //......
- return 0;
- }
点击(此处)折叠或打开
- void run() {
- pthread_detach(pthread_self());
- }
- int main(){
- pthread_t thread;
- pthread_create(&thread, NULL, run, 0);
- //......
- return 0;
- }
点击(此处)折叠或打开
- void run() {
- return;
- }
- int main(){
- pthread_t thread;
- pthread_create(&thread, NULL, run, 0);
- //......
- pthread_join(thread,NULL);
- return 0;
- }
正确使用pthread_create,防止内存泄漏的更多相关文章
- iOS 出现内存泄漏的几种原因
一.从AFNet 对于iOS开发者,网络请求类AFNetWorking是再熟悉不过了,对于AFNetWorking的使用我们通常会对通用参数.网址环境切换.网络状态监测.请求错误信息等进行封装.在封装 ...
- Android内存泄漏原因
这段时间调试APP的时候,发现程序在加载了过多的bitmap后会崩溃.查看了日志,原来是发生了内存溢出(OOM).第一次遇到这样的问题,那就慢慢排查吧. 内存优化可以参考胡凯大神的博客Android内 ...
- ios开发系列之内存泄漏分析(上)
ios自从引入ARC机制后,一般的内存管理就可以不用我们码农来负责了,但是一些操作如果不注意,还是会引起内存泄漏. 本文主要介绍一下内存泄漏的原理.常规的检测方法以及出现的常用场景和修改方法. 1. ...
- 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye
一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...
- java内存泄漏的几种情况
转载于http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静态 ...
- Android内存泄漏分享
内容概述 内存泄漏和内存管理相关基础. Android中的内存使用. 内存分析工具和实践. 以下内容不考虑非引用类型的数据,或者将其等同为对应的引用类型看待--一切皆对象. 内存泄漏概念 不再使用的对 ...
- .net中事件引起的内存泄漏分析
系列主题:基于消息的软件架构模型演变 在Winform和Asp.net时代,事件被大量的应用在UI和后台交互的代码中.看下面的代码: private void BindEvent() { var bt ...
- Android内存优化-内存泄漏的几个场景以及解决方式
转自:http://blog.csdn.net/a910626/article/details/50849760 一.什么是内存泄漏 在Java程序中,如果一个对象没有利用价值了,正常情况下gc是会对 ...
- 【原创】android内存管理-内存泄漏原因
转载请注明出处 http://www.cnblogs.com/weiwangnuanyang/p/5704596.html 先讲一下内存泄漏的概念:内存泄露是指无用对象持续占有内存,或者内存得不到及时 ...
随机推荐
- Xcode 6 打包ipa文件
随着Xcode6.1的普遍应用.随之而来的非常多问题就会出现.这里来说一下怎样在Xcode6.1上生成Ad-hoc ipa.首先是要在你的开发人员账号上生成一个.ipa的主要应用就是在你公布到AppS ...
- 78.pipe多管道云端,客户端通信
压力测试截图: 云端 定义管道缓存区大小,最多连接数量(线程个数),当前线程个数,管道名字 //缓冲区大小 #define SIZE 4096 //最多连接数量 #define MAX_CONNECT ...
- 父子margin塌陷
1.使用padding 2.给父级使用border 3.给父级添加属性 overflow:hidden 4.浮动 5.定位{absolute,fixed} 6.伪元素代码 .parent:before ...
- 使用PyCharm安装第三方库
使用PyCharm安装第三方库是一种十分简单的做法,接下来我来演示一下在PyCharm上安装第三方库requess的操作流程. 首先,先看一下当第三方库未安装时的提示内容,在pycharm中新建pyt ...
- 【2017百度之星程序设计大赛 - 复赛】Valley Numer
[链接]http://acm.hdu.edu.cn/showproblem.php?pid=6148 [题意] 在这里写题意 [题解] 先把1..N里面的山峰数字个数算出来->x 然后用N减去这 ...
- 洛谷 P2978 [USACO10JAN]下午茶时间Tea Time
P2978 [USACO10JAN]下午茶时间Tea Time 题目描述 N (1 <= N <= 1000) cows, conveniently numbered 1..N all a ...
- 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)
poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...
- Behavioral模式之Visitor模式
1.意图 表示一个作用于某对象结构中的各元素的操作.它使你能够在不改变各元素的类的前提下定义作用于这些元素的新操作. 2.别名 无 3.动机 考虑一个编译器.他将源程序表示为一个抽象语法树.该编译器须 ...
- activity-栈相关属性
1.启动任务栈 第一种,动作设置为“android.intent.action.MAIN”,类别设置为“android.intent.category.LAUNCHER”,可以使这个ACT(activ ...
- matlab 局部特征检测与提取(问题与特征)
物体识别:SIFT 特征: 人脸识别:LBP 特征: 行人检测:HOG 特征: 0. 常见手工设计的低级别特征 manually designed low-level features 语音:高斯混合 ...