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

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
extern "C" JNIEXPORT void JNICALL Java_com_sisheng_fitscreen_pose_Yolov8Pose_openRtspUrl( JNIEnv *env, jobject, jobjectArray rtspUrlArr, jobjectArray cameraIdArr ) { isOpenRtsp = true; jsize length = env->GetArrayLength(rtspUrlArr); int ii = 0; for (jsize i = 0; i < length; ++i) { jstring jRtspUrlElement = (jstring) (env->GetObjectArrayElement(rtspUrlArr, i)); jstring jCameraIdElement = (jstring) (env->GetObjectArrayElement(cameraIdArr, i)); // 创建全局引用 jobject rtspUrlGlobalStringRef = (jstring) env->NewGlobalRef(jRtspUrlElement); jobject cameraIdGlobalStringRef = (jstring) env->NewGlobalRef(jCameraIdElement); const char *cRtspUrlElement = env->GetStringUTFChars(jRtspUrlElement, nullptr); const char *cCameraIdElement = env->GetStringUTFChars(jCameraIdElement, nullptr); // 准备要传递给线程的数据 ThreadData *data = new ThreadData(); data->url = cRtspUrlElement; data->cameraId = cCameraIdElement; data->indexStr = std::to_string(ii); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "xxxxxxxxxx ii: %i a:%s", ii, data->indexStr.c_str()); ii++; pthread_t thread_1; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thread_1, NULL, open_media, data) != 0) { // 错误处理:释放全局引用并删除data env->DeleteGlobalRef(rtspUrlGlobalStringRef); env->DeleteGlobalRef(cameraIdGlobalStringRef); env->ReleaseStringUTFChars(jRtspUrlElement, cRtspUrlElement); env->ReleaseStringUTFChars(jCameraIdElement, cCameraIdElement); env->DeleteLocalRef(jRtspUrlElement); env->DeleteLocalRef(jCameraIdElement); __LOG_PRINT(ANDROID_LOG_ERROR, "rtsp", "delete data"); delete data; } // 立即释放本地引用 env->ReleaseStringUTFChars(jRtspUrlElement, env->GetStringUTFChars(jRtspUrlElement, nullptr)); env->ReleaseStringUTFChars(jCameraIdElement, env->GetStringUTFChars(jCameraIdElement, nullptr)); env->DeleteLocalRef(jRtspUrlElement); env->DeleteLocalRef(jCameraIdElement); pthread_attr_destroy(&attr); } }这个代码在配置多个摄像头时会出现段错误,分析可能的原因?会不会和调用端有关?
03-30
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值