3ka5_cat
3ka5_cat

Reputation: 131

Destructor issue of shared_ptr<std::deque>, passed as argument to new thread

I pass params structure, which contains shared_ptr to std::deque, as input argument for function, which would work in a new thread. This deque created on the external object as a public field. And when I save shared_ptr to the params structure, number of refs at shared_ptr is incremented, and all seems to be ok.

As for thread, it is created with help of calling _beginthread() function. Inside the thread, I push some values to deque, pointed by shared_ptr. These values are popped at the external object correctly, so everything seems to be ok again.

When thread finishes it's work, params structure deleted from heap and ref counter decremented (all is fine again). But when destructor of external object, where this shared_ptr was created, is called then refs counter is decremented and equals 0, so destructor of pointed object is actually called, and debug assertation failure appears. Failed expression is _pFirstBlock == pHead (double delete?). But I checked with help of Data breakpoint at VS2012, that address of shared_ptr._Rep._Uses is only accessed at moments I described above.

One more note: if nothing pushed into this deque, then all destructors run successfully. What I'm doing wrong?

typedef std::deque<MsgBuf_ptr> MsgQueue;
typedef std::tr1::shared_ptr<MsgQueue> MsgQueue_ptr;
typedef const MsgQueue_ptr& MsgQueue_ptr_p;

shared_ptr creation:

...
MsgQueue_ptr qMsgQueue;
...
qMsgQueue.reset(new MsgQueue)
...
bool bStartOK = start(qMsgQueue, ghMutex);  

thread param structure:

struct ThreadServerParam {  
    HANDLE ghStopEvent;
    MsgQueue_ptr qMsgQueue; 
    HANDLE ghMutex;
};

thread creation:

void start(MsgQueue_ptr_p qMsgQueue, HANDLE ghMutex) {
    param = new ThreadServerParam;
    param->qMsgQueue = qMsgQueue;   
    param->ghStopEvent = ghStopEvent;
    param->ghMutex = ghMutex;

    hThread = (HANDLE)_beginthread( &ThreadFunction, THREAD_STACK_SIZE, param );
    if(hThread == INVALID_HANDLE_VALUE || hThread == NULL) {...}
}

thread function:

void ThreadFunction(void* ptr) {
    ThreadServerParam *param = (ThreadServerParam*) ptr;    
    while(dwWaitResult != WAIT_OBJECT_0) {          
        findNewMessage(internalQueue);
        if(!msgQueue->empty()) {                
        DWORD dwWaitResult = WaitForSingleObject(param->ghMutex, INFINITE);
        switch (dwWaitResult) {
                case WAIT_OBJECT_0: 
                    while (!msgQueue->empty()) {
                        MsgBuf_ptr msg_buf = internalQueue->front();
                        param->qMsgQueue->push_back(msg_buf);                                   
                        internalQueue->pop_front();
                    }
             ...
            }
          }
          Sleep(GAP);
      dwWaitResult = WaitForSingleObject(param->ghStopEvent, 0);
     }
     delete param;
 }

Upvotes: 0

Views: 618

Answers (0)

Related Questions