避免使用不当pthread_create函数造成内存泄露

本文深入剖析了在Linux应用进程中使用pthread_create创建线程时,由于线程非分离状态导致的内存占用过大问题。通过提供三种方法:创建分离线程、线程结束前分离、主线程等待线程结束,旨在解决内存泄露问题。最终,作者发现fork方式在减少内存资源占用方面更为有效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pthread_create使用不当会造成内存泄漏,对于内存不大的开发板会造成严重后果。

问题:dlna主进程中使用pthread_create创建两个线程scan和inotify,造成内存占用率过大,导致crash。

产生根源:pthread_create默认创建的线程是非detached的。

预防方式:要么创建detached的线程,要么在非detached线程结束之前detached,或者在主进程中join。

线程的分离状态决定线程以什么样的方式来终止自己。线程的默认属性是非分离状态,这种情况下,主进程等待新进程结束,只有当pthread_join函数返回时,新进程才终止,才会释放所占有系统资源。而分离线程则不同,不会被主进程等待,运行结束进程也就终止,立即释放系统资源。pthread_create创建的进程默认是分配8M左右的内存空间,该参数可调整,使用不当回造成改内存空间一直被占用,直至主进程结束才一起释放。


避免内存泄露的几种使用方法:

方法一、创建detached的线程
  1. void run() { 
  2.     return;
  3. } 
  4.                                                                                                        
  5. int main(){ 
  6.     pthread_t thread; 
  7.     pthread_attr_t attr; 
  8.     pthread_attr_init( &attr ); 
  9.     pthread_attr_setdetachstate(&attr,1); 
  10.     pthread_create(&thread, &attr, run, 0); 
  11.           
  12.     //...... 
  13.     return 0; 
  14. }

方法二、线程结束之前detached
  1. void run() { 
  2.     pthread_detach(pthread_self()); 
  3. } 
  4.                                                                                                        
  5. int main(){ 
  6.     pthread_t thread;  
  7.     pthread_create(&thread, NULL, run, 0); 
  8.               
  9.     //...... 
  10.     return 0; 
  11. }

方法三、主线程使用pthread_join
  1. void run() { 
  2.     return;
  3. } 
  4.                                                                                                        
  5. int main(){ 
  6.     pthread_t thread; 
  7.     pthread_create(&thread, NULL, run, 0);  
  8.                                        
  9.     //...... 
  10.     pthread_join(thread,NULL);
  11.     return 0; 
  12. }
其实在linux应用进程中,尝试了上述所有的方法,都并没有起到减少内存资源一直被占用的效果,最后迫不得已采用fork方式取代pthread_create方式才有减少内存资源占用的效果。

``` Task stTaskQueue[256]; int iTaskCount = 0; pthread_mutex_t stMutexQueue; pthread_cond_t stCondQueue; void* PthreadPoolWorker(void* arg) { Task* pstTask; while(g_iExit == 0) { pthread_mutex_lock(&stMutexQueue); while(iTaskCount == 0) { pthread_cond_wait(&stCondQueue, &stMutexQueue); } pstTask = &stTaskQueue[--iTaskCount]; pthread_mutex_unlock(&stMutexQueue); pstTask->task(pstTask->arg); } } int ThreadPoolSubmit(void* (*task)(void*),void* arg) { int iRet = -1; if(pthread_mutex_lock(&stMutexQueue) != 0) { cmn_PrtError("Error in locking mutex"); } if(iTaskCount > 255) { pthread_mutex_unlock(&stMutexQueue); cmn_PrtError("Error in queue overflow"); } stTaskQueue[iTaskCount].task = task; stTaskQueue[iTaskCount].arg = arg; iTaskCount++; if(pthread_mutex_unlock(&stMutexQueue) != 0) { cmn_PrtError("Error in unlocking mutex"); } if(pthread_cond_signal(&stCondQueue) < 0) { cmn_PrtError("Error in signaling condition"); } iRet = 0; _Exit: return iRet; } int ThreadPoolInit(void) { int iRet = -1; if(pthread_mutex_init(&stMutexQueue, NULL) <0) { cmn_PrtError("Error in initializing mutex"); } if(pthread_cond_init(&stCondQueue, NULL)) { cmn_PrtError("Error in initializing condition"); } for(int i = 0; i < 5; i++) { pthread_t stThread; pthread_create(&stThread, NULL, PthreadPoolWorker, NULL); pthread_detach(stThread); } iRet = 0; _Exit: return iRet; }```int ThreadPoolDestroy(void) { int iRet = -1; g_iExit = 1; if(pthread_mutex_lock(&stMutexQueue)!= 0) { cmn_PrtError("Error in locking mutex"); } while(iTaskCount > 0) { pthread_cond_wait(&stCondQueue, &stMutexQueue); } if(pthread_mutex_unlock(&stMutexQueue)!= 0) { cmn_PrtError("Error in unlocking mutex"); } if(pthread_cond_broadcast(&stCondQueue) < 0) { cmn_PrtError("Error in broadcasting condition"); } if(pthread_mutex_destroy(&stMutexQueue)!= 0) { cmn_PrtError("Error in destroying mutex"); } if(pthread_cond_destroy(&stCondQueue)!= 0) { cmn_PrtError("Error in destroying condition"); } iRet = 0; _Exit: return iRet; } 检查代码是否有bug,并给出解决方案
03-13
``` Task stTaskQueue[256]; int iTaskCount = 0; pthread_mutex_t stMutexQueue; pthread_cond_t stCondQueue; pthread_t stThreadAry[cmnDfn_WORKING_PTHREAD_NUMBER]; void* PthreadPoolWorker(void* arg) { Task* pstTask; g_iExit = 0; while(g_iExit == 0) { if(pthread_mutex_lock(&stMutexQueue)) { cmn_PrtError("Error in locking mutex"); } while(iTaskCount == 0) { pthread_cond_wait(&stCondQueue, &stMutexQueue); } pstTask = &stTaskQueue[--iTaskCount]; if(pthread_mutex_unlock(&stMutexQueue)) { cmn_PrtError("Error in unlocking mutex"); } pstTask->task(pstTask->arg); } _Exit: pthread_exit(NULL); } int ThreadPoolSubmit(void* (*task)(void*),void* arg) { int iRet = -1; if(pthread_mutex_lock(&stMutexQueue) != 0) { cmn_PrtError("Error in locking mutex"); } if(iTaskCount > 255) { pthread_mutex_unlock(&stMutexQueue); cmn_PrtError("Error in queue overflow"); } stTaskQueue[iTaskCount].task = task; stTaskQueue[iTaskCount].arg = arg; iTaskCount++; if(pthread_mutex_unlock(&stMutexQueue) != 0) { cmn_PrtError("Error in unlocking mutex"); } if(pthread_cond_signal(&stCondQueue) < 0) { cmn_PrtError("Error in signaling condition"); } iRet = 0; _Exit: return iRet; } int ThreadPoolInit(void) { int iRet = -1; int iLoopNum; if(pthread_mutex_init(&stMutexQueue, NULL) <0) { cmn_PrtError("Error in initializing mutex"); } if(pthread_cond_init(&stCondQueue, NULL)) { cmn_PrtError("Error in initializing condition"); } for(iLoopNum = 0; iLoopNum < 5; iLoopNum++) { pthread_create(&stThreadAry[iLoopNum], NULL, PthreadPoolWorker, NULL); } iRet = 0; _Exit: return iRet; } int ThreadPoolDestroy(void) { int iRet = -1; g_iExit = 1; int iLoopNum; if(pthread_mutex_lock(&stMutexQueue)!= 0) { cmn_PrtError("Error in locking mutex"); } while(iTaskCount > 0) { pthread_cond_wait(&stCondQueue, &stMutexQueue); } if(pthread_mutex_unlock(&stMutexQueue)!= 0) { cmn_PrtError("Error in unlocking mutex"); } if(pthread_cond_broadcast(&stCondQueue) < 0) { cmn_PrtError("Error in broadcasting condition"); } for(iLoopNum = 0; iLoopNum < cmnDfn_WORKING_PTHREAD_NUMBER; iLoopNum++) { if(pthread_join(stThreadAry[iLoopNum], NULL)) { cmn_PrtError("Error in joining thread"); } } if(pthread_mutex_destroy(&stMutexQueue)!= 0) { cmn_PrtError("Error in destroying mutex"); } if(pthread_cond_destroy(&stCondQueue)!= 0) { cmn_PrtError("Error in destroying condition"); } iRet = 0; _Exit: return iRet; }```检查代码是否有bug并给出解决方案
03-13
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值