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

来源:互联网 发布:鼠标质量排行 知乎 编辑:程序博客网 时间:2024/06/05 17:41

用 top 发现 virt 的使用量一直在涨,于是可以断定有内存泄露(也可以查看 /proc/<pid>/maps ,相应 pid 进程的 maps 文件中出现了很多内存碎片,也说明内存泄露)。经过排查,最终确定问题出现在多线程上。如图:



查询资料了解到: 

(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.

当一个可结合线程终止时,它的内存资源(线程描述符和堆栈)就不会被释放,直到另一个线程在它上执行 pthread_join。因此,为了避免内存泄露,必须为每个可连接的线程调用 pthread_join


(2)《Linux高级编程》里是这样讲的:
可接合(非分离态的,需要等待)的线程,就像一个进程一样,当它执行结束时,并没有被GNU/Linux自动清理,而它的退出状态却仍在系统内挂着(这有点像僵尸进程),直到另一个线程调用pthread_join()获取其返回值时,其资源才被释放。


在 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,或等待,同步)子线程,同事释放线程本身占用的资源。否则,线程资源将驻留内存,直到整个进程退出为止,若进程会不断的创建线程,则每创建一次线程都会导致内存资源的消耗,很明显,这样就会构成内存泄露。



对于线程资源的释放,主要分为2类:

第一类,调用 pthread_join()


第二类,将线程属性设为分离状态(detached)

 1、 创建线程时,设置线程属性为分离线程

pthread_t t;pthread_attr_t a; //线程属性pthread_attr_init(&a);  //初始化线程属性pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);      //设置线程属性pthread_create( &t, &a, GetAndSaveAuthviewSDRStub, (void*)lp);                   //建立线程

2、在线程中将自己设为分离线程

pthread_detach(pthread_self())



阅读全文
1 0
原创粉丝点击