c++ - Heap (HeapAlloc) Corruption in release mode only -


i want guys understand root cause of heap corruption. sharing code flow , little code base below:

flow :

  1. main thread receives n jobs.
  2. main thread creates pool of thread(100) , executor thread , jobqueue(thread creation code shared below ).executor keeps checking jobqueue job in infinite while loop , wakes worker thread when receives job jobqueue.
  3. main thread post job jobqueue picked executor thread , start processing.
  4. when executor thread gets signal job completion, signals main thread of job completion(by registered call back).
  5. in callback, main thread checks whether jobs done or not. if there jobs, return false executor thread , post next job jobqueue , step 4 gets executed.

if jobs processed, main thread return true executor thread , main thread start terminating threads , executor thread breaks infinite while loop. (terminate thread , clean code shared below).

problem statement : when first set of job finishes, main thread terminates worker , executor thread , releases memory.if main thread receives next set of job, exception happened randomly anywhere , shows heap corruption issue. issue not occur in release mode.

thread pool creation

static job* create (int numworker)     {         jobce* te = new jobce ();          te->_paworkerthreadinfo = new workerthreadinfo_t* [numworker];         te->_phthread           = new handle [numworker];         te->_pthreadid          = new dword [numworker];         te->_numworker          = numworker;          te->_hmutex = createmutex (null, false, null);         if (null == te->_hmutex)         {             return 0;         }          (int = 0; < numworker; i++)         {             te->_paworkerthreadinfo [i] = null;             te->_phthread [i]           = null;             te->_pthreadid [i]          = 0;         }           /* create worker threads */         (inti = 0; < numworker; i++)         {             te->_paworkerthreadinfo [i] = (workerthreadinfo_t*) heapalloc (                 getprocessheap (),                 heap_zero_memory,                 sizeof (workerthreadinfo_t));             if (te->_paworkerthreadinfo [i] == null)             {                 delete te;                 exitprocess (0);             }              te->_paworkerthreadinfo [i]->pjobexecuter = te;             te->_paworkerthreadinfo [i]->hwakeupevent = createevent (null,                  false,                 false,                  null);             if (null == te->_paworkerthreadinfo [i]->hwakeupevent)             {                 delete te;                 /* log error */                 exitprocess (0);             }              te->_paworkerthreadinfo [i]->hexitevent = createevent (null,                  true,                 false,                  null);             if (null == te->_paworkerthreadinfo [i]->hexitevent)             {                 delete te;                 exitprocess (0);             }              te->_paworkerthreadinfo [i]->hthreadstopped = createevent (null,                  true,                 false,                 null);             if (te->_paworkerthreadinfo [i]->hthreadstopped == null)             {                 exitprocess (0);             }              te->_paworkerthreadinfo [i]->bbusy = false;              /* create thread */             te->_phthread [i] = createthread (null,                 0,                 workerthread,                 te->_paworkerthreadinfo [i],                 0,                 te->_pthreadid + i);             if (te->_phthread [i] == null)             {                 delete te;                 exitprocess (0);             }         }          /* create job executer thread */         te->_hexecthread = createthread (null,             0,             executerthread,              te,             0,             &(te->_execthreadid));         if (te->_hexecthread == null)         {             delete te;             exitprocess (0);         }          return te;     } 

terminate , cleanup threads :

void terminatethreads(void){         log_error_0("waiting thread object");         waitformultipleobjects(100, this->_phthread, true, infinite);         log_error_0("waiti on threads");         (int = 0; i<_numworker; i++) {             setevent(this->_paworkerthreadinfo[i]->hexitevent);              closehandle (this->_paworkerthreadinfo[i]->hexitevent);             closehandle (this->_paworkerthreadinfo[i]->hthreadstopped);             closehandle (this->_paworkerthreadinfo[i]->hwakeupevent);             closehandle (this->_phthread[i]);         }          waitforsingleobject(this->_hexecthread, infinite);                 log_error_0("waiting single object");         closehandle(this->_hexecthread);                     log_error_0("wait over");      }      void cleanup (void)     {         (int = 0; < _numworker; i++)         {             heapfree(getprocessheap(), 0, _paworkerthreadinfo [i]);         }         if( _pthreadid != null )         {             delete[] _pthreadid;             _pthreadid = null;         }          if( _phthread != null )         {             delete[] _phthread;             _phthread = null;         }         if(_hexecthread != null) {             _hexecthread = null;         }            if( _immjobqueue != null )         {             delete _immjobqueue;             _immjobqueue = null;         }         if( _jobqueue != null )         {             delete _jobqueue;             _jobqueue = null;         }         if( _paworkerthreadinfo != null )         {             delete[] _paworkerthreadinfo;             _paworkerthreadinfo = null;         }     }  typedef struct {     jobce*          pjobce;     handle          hwakeupevent;     handle          hexitevent;     handle          hthreadstopped;     bool            bbusy;  } workerthreadinfo_t; 

any appreciated.

i can guess why wouldn't check result of heapfree? because according documentation reason. try use heap_no_serialize flag when allocate heap.

you should not refer in way memory has been freed heapfree. after memory freed, information may have been in gone forever. if require information, not free memory containing information. function calls return information memory (such heapsize) may not used freed memory, may return bogus data. calling heapfree twice same pointer can cause heap corruption, resulting in subsequent calls heapalloc returning same pointer twice.

serialization ensures mutual exclusion when 2 or more threads attempt simultaneously allocate or free blocks same heap. there small performance cost serialization, must used whenever multiple threads allocate , free memory same heap. setting heap_no_serialize value eliminates mutual exclusion on heap. without serialization, 2 or more threads use same heap handle might attempt allocate or free memory simultaneously, causing corruption in heap. heap_no_serialize value can, therefore, safely used in following situations:

the process has 1 thread. process has multiple threads, 1 thread calls heap functions specific heap. process has multiple threads, , application provides own mechanism mutual exclusion specific heap. 

Comments

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -