Use pthread_create properly to prevent memory leaks

Source: Internet
Author: User

Original source: http://www.cnblogs.com/lidabo/p/5514100.html


Recently, I heard that pthread_create will cause memory leaks, it is incredible, so the POSIX (NPTL) thread creation and destruction are analyzed. Analysis results: if used incorrectly, it does cause a memory leak. root cause : Pthread_create The thread created by default is detached. Prevention: Either create a detached thread, either before the thread's start_routine ends detached, or the join analysis process is as follows: 1. View Pthread_create source Code, The core code is as follows (NPTL/PTHREAD_CREATE.C):

Click (here) to collapse or open int __pthread_create_2_1  (NEWTHREAD, ATTR, START_ROUTINE, ARG)       pthread_t *newthread;      const pthread_attr_t *attr;      void * (*start_routine)   (void *);        void *arg; {  STACK_VARIABLES;   const struct pthread_attr *iattr =  (struct pthread_ attr *)  attr;   if  (Iattr == null)     /* is this the best idea? on  numa machines This could mean        accessing Far-away memory. */     iattr = &default_attr;   struct pthread *pd = null;   int err = Allocate_stack (iattr, &PD);//Allocate memory for TCB   if  (__builtin_expect  (Err  != 0, 0))       /*&nbsp Something went wrong. maybe a parameter of the Attributes is         Invalid or we could not allocate memory. */    return err; ... err = Create_thread (PD, IATTR, Stack_variables_args);//formally Create thread  2. View CREATETHREAD.C (NPTL/SYSDEPS/PTHREAD/CREATETHREAD.C)

Click (here) to collapse or open the static int create_thread (struct pthread *pd, const struct, pthread_attr *attr, Stack_variables_par MS) {#ifdef TLS_TCB_AT_TP assert (PD->HEADER.TCB!= NULL); #endif//... int res = Do_clone (PD, attr, Clone_flags, start_thread, Stack_variables_args, 1);//clone a Process 3. Then see Start_thread (NPTL/PTHREAD_CREATE.C) did What

Click (here) to collapse or open static int start_thread  (void *arg) {  struct pthread *pd =  ( struct pthread *)  arg; ...       /* run the code the user provided. */#ifdef CALL_THREAD_FCT  & nbsp;    thread_setmem  (pd, result, call_thread_fct  (PD));  #else       thread_setmem (PD, result, Pd->start_routine (Pd->arg));  // Officially start the execution of the thread and wait for execution to complete #endif//... if (is_detached (PD))    /* Free the TCB.  */    __FREE_TCB (PD);//If the detached flag is set, the content of the TCB is released, otherwise the direct return   else if (__builtin_expect Cancelhandling & Setxid_bitmask, 0)     {     /* Some other thread might call any of the S Etxid functions and expect      us to reply.  in This case wait until we did that.  */      do     lll_futex_wait (&pd->setxid_futex, 0, LLl_private);       while (pd->cancelhandling & Setxid_bitmask);      /Reset The value so this stack can be reused.  */      Pd->setxid_futex = 0;    } from the above procedure, we can see that if the detached flag is not set when the thread is created, TCB memory will never be released   Next, let's look at what Pthread_detach (npth/pthread_detach.c) did

Click (here) to collapse or open the int pthread_detach  (TH)      pthread_t th;  {  struct pthread *pd =  (struct pthread *)  th;    /* make sure the descriptor  is valid. */  if  (invalid_not_terminated_td_p  (PD))      /* not a valid thread handle. */    return esrch;   int result = 0;   /* mark the thread as detached. */  if  (Atomic_compare_and_exchange_bool_acq   (&pd->joinid, pd, null))     {         /* there are two possibilities here. first, the thread might       Already be detached. in this case we return einval.      otherwise there might already be a waiter. the standard does       Not mention What happens in this case. */      if  ( is_detached  (PD))     result = EINVAL;     }    else     /* check whether the thread terminated Meanwhile. in this case we        will just free the TCB.  */    if  ((pd->cancelhandling & exiting_bitmask)  !=  0)       /* note that the CODE IN __FREE_TCB makes sure each  Thread      control block is freed only once. */       __FREE_TCB (PD);//After a series of fault-tolerant judgment, direct release TCB occupied memory   return result; } Finally, let's take a look at what Pthread_join (NPTL/PTHREAD_JOIN.C) did

Click (here) to collapse or open the int pthread_join  (threadid, thread_return)      pthread_t ThreadID;      void **thread_return; {  struct pthread *pd =  (struct pthread *)  threadid;   /* make Sure the descriptor is valid. */  if  (invalid_not_terminated_td_p  (PD))      /* not a valid thread handle. */    return ESRCH;   /* is the thread joinable?  */  if  (is_detached  (PD))     /* we cannot wait for  The thread. */    return einval;   struct pthread *self = thread_self;   int result = 0;   /* during The wait we change to asynchronous cancellation. if we       are canceled the thread we are WaitiNg for must be marked as      un-wait-ed for again. */   pthread_cleanup_push  (Cleanup, &pd->joinid);   /* switch to asynchronous cancellation. */  int oldtype =  CANCEL_ASYNC  ();   if  (pd == self        | |   (SELF->JOINID == PD      &&  (pd->cancelhandling      &  (Canceling_bitmask | canceled_bitmask | exiting_ Bitmask          | terminated_bitmask))  == 0)       && ! cancel_enabled_and_canceled  (self->cancelhandling))     /* this is a Deadlock situation. the threads are Waiting for each       &nbSp;other to finish. note that this is a  ' may '  error. to be 100%        sure we catch This error we would have to lock the data        structures but it is not necessary. in the Unlikely case that        two threads are really caught in  This situation they would        deadlock. it is the programmer ' s Problem to figure this        out. */     result = edeadlk;   /* wait for the Thread to finish. if it is already Locked something      is wrong. there can only one waiter. */   else if  (__builtin_expect  (atomic_compare_and_exchange_bool_acq  (&pd->joinid,                                    Self,                                    NULL),  0)     /* there is already somebody waiting for the thread. */    result = EINVAL;   else     /* wait for the child. */     lll_wait_tid  (Pd->tid);   /* restore cancellation mode. */  CANCEL_RESET  (Oldtype);   /* remove the handler. */  pthread_cleanup_pop  (0);   if  (__builtin_expect  (RESULT ==&NBsp;0, 1))     {      /* we mark the thread as terminated  and as joined. */      pd->tid = -1;       /* store The return value if the caller is interested .  */      if (Thread_return!= NULL)
*thread_return = pd->result;//Set return value
/* Free the TCB. */
__FREE_TCB (PD);/release TCB occupy memory} return result; In summary, if you want to ensure that there is no memory leak after creating the thread, you must use the following methods to standardize the pthread_create:method One, creating the detached thread

Click (here) to collapse or open void run ()  {      return;                                                                                                                Int main () {      pthread_t thread;      pthread_attr_t attr;       pthread_attr_init ( &attr );      pthread_attr_setdetachstate (&attr,1);      pthread_create (&thread, &attr, run, 0);                 // ......      return 0; } method Two, or before the start_routine end of the thread thread detached

Click (here) to collapse or open void run ()  {      pthread_detach (Pthread_self ()); }                                                                                                                Int main () {       pthread_t thread;       pthread_create (&thread, NULL,  run, 0);                     //......    &nbsP; return 0; } method Three, main thread uses Pthread_join

Click (here) to collapse or open void run ()  {      return;                                                                                                                Int main () {      pthread_t thread;      pthread_create (&thread, NULL,  run, 0);                                            &NBSp;  //......      Pthread_join (thread,null);     return 0; }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.