隐蔽的内存泄漏——pthread_create 属性设置不当导致


最近解决了一个隐蔽的内存泄漏问题,我们的进程是HA模式,用户不停的切换,会导致内存不停的增长,切换一次,再切回来内存便增加8M左右。原因就是是pthread_create后的僵死线程没有释放导致的内存持续增长。


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的话,线程的资源会一直得不到释放而导致内存泄漏!


解决办法


创建线程前设置 PTHREAD_CREATE_DETACHED 属性
 pthread_attr_t attr;
 pthread_t thread;
 thread_attr_init (&attr);
 pthread_attr_setdetachstate (&attrPTHREAD_CREATE_DETACHED);
 pthread_create (&thread, &attr&thread_function, NULL);
 pthread_attr_destroy (&attr);

这样就会在线程return/pthread_exit后释放内存。

其实用valgrind检查时会提示pthread_create没有释放的问题,这样的问题也只有在长时间运行时,慢慢积累这一点点的内存才会暴露出来。



属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数 之前调用。属性对象主要包括是否绑定、是否分离、堆栈地址、堆栈大小、优先级。默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。

线程的分离状态决定一个线程以什么样的方式来终止自己。在上面的例子中,我们采用了线程的默认属性,即为非分离状态,这种情况下,原有的线程等待 创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其 他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。设置线程分离状态的函数为pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)。




你可能感兴趣的:(C/C++)