Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4958061
  • 博文数量: 1696
  • 博客积分: 10870
  • 博客等级: 上将
  • 技术积分: 18357
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-30 15:16
文章分类
文章存档

2017年(1)

2016年(1)

2015年(1)

2013年(1)

2012年(43)

2011年(17)

2010年(828)

2009年(568)

2008年(185)

2007年(51)

分类: LINUX

2010-05-28 00:17:32

Linux程序设计中由线程使用不当引起的内存泄漏

                                      
Linux程序设计中,创建线程时调用pthread_create()函数,该函数原型如下:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
其中第二个参数attr为线程属性指针,一般情况 下,我们创建线程时,若对线程属性没有特殊要求,都将此参数设为NULL,这也就使用了线程的默认属性- 非分离状态(joinable,或称可接合状态),之后,主线程必须在适当的时候调用pthread_join(),来接合(join,或等待,同步)子 线程,同时释放线程本身占用的资源;否则,线程资源将驻留内存,直到整个进程退出为止.若进程会不断的创建线程,则每创建一次线程都会导致内存资源的消 耗,很明显,这已经构成了内存泄漏!

关于这个问题,举出本人查到的佐证
1)) 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.
2)) <>里是这样讲的:
可接合(需要等待)的线程,就像一个进程一样,当它执行结束时,并没有被 GNU/Linux自动清理,而它的退出状态却仍在系统内挂着(这有点像僵尸进程),直到另一个线程调用pthread_join()获取其返回值时,其 资源才被释放.

对于线程资源的释放,有两种实现方法:
(1) 线程创建时,默认属性是可接合的(joinable),那就需要主线程来等待,所以在创建这个线程后适当的时候就必须调用pthread_join()来 等待子线程结束执行,否则就会引起内存泄漏!

在调用pthread_create()开线程后,若线程属性是 joinable,则必须调用pthread_join()来等待子线程结束执行,这是 Linux同步主线程和子线程的一个机制,但是,这并不等于说,我要在pthread_create()开线程后立即调用pthread_join()来 等待该线程结束执行,的确,那样的话跟你用普通函数调用来实现是没有区别的,你完全可以在pthread_create()开线程后去做别的事情,等你觉 得应该等待该线程结束执行时再调用pthread_join().这就是说,假如你的线程采用了默认属性joinable,你就必须在适当的时候调用 pthread_join()来同步主线程和子线程,同时释放子线程的资源(线程描述符和堆栈(thread descriptor and stack)).
假如你用了默认线程属性,即线程属性为joinable,而又没有在适当的时候调用pthread_join(),那么该线程所 占用的资源便不会被释放(kind of like a zombie process),因此造成内存泄漏.
假如你不想或没有必 要同步主线程和子线程,那么就把子线程属性设置为detached分离状态,那么子线程结束执行后会自行销毁其占用的资源.
(2) 将线程属性设为分离状态(detached),这个样子线程就属于自灭那种,子线程函数启动后跟主线程不再有"父子"关系(等待和被等待),退出线程时其 资源会释放.注意:创建线程时,若属性参数为NULL,则线程属性默认为可接合的(joinable,即需要主线程等待的).
可以在线程创建时将 其属性设为分离状态(detached),也可在线程创建后将其属性设为分离的(detached).

#include
void* thread_function (void* thread_arg)
{
pthread_exit(“Exiting from the thread_function!”);
}
int main ()
{
pthread_t thr;
void* thread_result;
   pthread_create (&thr, NULL, &thread_function, NULL);
pthread_join(thr, &thread_result);
return 0;
}
 
(2) 将线程属性设为detached的两种方法的代码框架,
<1> Example Code of Setting a Thread DETACHED(1)
   
    在线程创建时,通过属性变量设置

#include
void* thread_function (void* thread_arg)
{
 pthread_exit(….);
}
int main ()
{
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);
return 0;
}
<2> Example Code of Setting a Thread DETACHED(2)
   
    线程创建后,通过调用pthread_detach()来设置

#include
void* thread_function (void* thread_arg)
{
   pthread_exit(....);
}
int main ()
{
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
pthread_detach(thread); 
return 0;
}
阅读(974) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~