解决了一个隐蔽的内存泄漏——pthread_create后没有detach导致内存持续增长

240 篇文章 2 订阅

昨天解决了一个隐蔽的内存泄漏问题,原因是pthread_create后的僵死线程没有释放导致的内存持续增长。
现象是这样的:短时间内程序运行正常,但跑了12小时左右,用top查看其内存占用居然高达2G,于是马上意识到有内存泄漏。

最先想到的是malloc/free、new/delete没有配对,申请的内存没有释放。于是写了个跟踪malloc/free调用的模块,不过检查中并没有找到未释放的内存。之后怀疑是不是 free then malloc 导致的内存管理错误(事实证明虽然free后不是立即回收内存,但是接连调用free & malloc并不会影响操作系统的内存管理),不过写了个小程序发现并不是这么回事。

陷入窘境了,只好用最小系统法把功能部分和内存分配都给屏蔽掉,这时发现内存泄漏依然存在!仔细看top的输出,几乎是每次创建线程时内存就往上涨一点,只是增长速度不是很快,看来是线程的问题了。仔细分析发现,之前图简单 pthread_create (&thread, NULL, &thread_function, NULL); 就这么写了,参数2没有设置线程结束后自动detach,并且没有使用pthread_join或pthread_detach释放执行结束后线程的空间!

Linux man page 里有已经说明了这个问题:
    When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called  once  for each joinable thread created to avoid memory leaks.

也就说线程执行完后如果不join的话,线程的资源会一直得不到释放而导致内存泄漏!一时的图快后患无穷啊。

解决办法

代码 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 1 // 最简单的办法,在线程执行结束后调用pthread_detach让他自己释放
 pthread_detach(pthread_self());
 
 
 // 或者创建线程前设置 PTHREAD_CREATE_DETACHED 属性
 pthread_attr_t attr;
 pthread_t thread;
 pthread_attr_init (&attr);
 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
 pthread_create (&thread, &attr, &thread_function, NULL);
 pthread_attr_destroy (&attr);

 

第2行的那种方法最简单,在线程函数尾部加上这句话就可以将线程所占用的资源给释放掉;或者像 5-11 所示的方法设置detach属性,这样也会在线程return/pthread_exit后释放内存。

其实仔细想想,valgrind检查时已经提示了pthread_create没有释放的问题,只是之前没引起注意。其实这样的问题也只有在长时间运行时,慢慢积累这一点点的内存才会暴露出来,看来valgrind的提示也不能置之不理啊。

 

from:

http://www.cnblogs.com/bits/archive/2009/12/04/no_join_or_detach_memory_leak.html


 

`pthread_detach(pthread_self())`函数的作用是将当前线程设置为分离状态,使得该线程结束时能够自动释放所有资源。这个函数的调用必须在线程结束前进行,否则会导致资源泄漏。 具体来说,`pthread_detach()`函数可以将一个线程设置为分离状态,这样当该线程结束时,系统会自动回收该线程所占用的资源,而不需要其他线程调用`pthread_join()`函数来等待该线程结束并回收资源。而`pthread_self()`函数则是获取当前线程的线程ID。 因此,`pthread_detach(pthread_self())`函数的作用就是将当前线程设置为分离状态,使得该线程结束时能够自动释放所有资源。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread_func(void *arg) { printf("Thread running...\n"); pthread_detach(pthread_self()); printf("Thread detached.\n"); pthread_exit(NULL); } int main() { pthread_t tid; int ret = pthread_create(&tid, NULL, thread_func, NULL); if (ret != 0) { printf("Create thread error!\n"); exit(1); } printf("Main thread running...\n"); pthread_exit(NULL); } ``` 在上面的示例代码中,我们创建一个新线程,并在该线程中调用了`pthread_detach(pthread_self())`函数将该线程设置为分离状态。在主线程中,我们调用了`pthread_exit(NULL)`函数来等待所有线程结束并回收资源。运行该程序,可以看到输出结果如下: ``` Main thread running... Thread running... Thread detached. ``` 可以看到,当新线程运行到`pthread_detach(pthread_self())`函数时,该线程被设置为分离状态,并在结束时自动释放了所有资源。而主线程则等待所有线程结束并回收资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值