C++ 共享ptr的析构函数问题<;标准::deque>;,作为参数传递给新线程

C++ 共享ptr的析构函数问题<;标准::deque>;,作为参数传递给新线程,c++,windows,multithreading,shared-ptr,beginthread,C++,Windows,Multithreading,Shared Ptr,Beginthread,我将包含shared_ptr的params结构传递给std::deque,作为函数的输入参数,该函数将在新线程中工作。在外部对象上创建的此数据块作为公共字段。当我将shared_ptr保存到params结构中时,shared_ptr中的引用数会增加,并且似乎一切正常 对于线程,它是通过调用\u beginthread()函数创建的。在线程内部,我将一些值推送到deque,由shared_ptr指向。这些值被正确地弹出到外部对象,因此一切似乎又正常了 当线程完成它的工作时,params结构从堆中删

我将包含
shared_ptr
的params结构传递给
std::deque
,作为函数的输入参数,该函数将在新线程中工作。在外部对象上创建的此数据块作为公共字段。当我将shared_ptr保存到
params
结构中时,shared_ptr中的引用数会增加,并且似乎一切正常

对于线程,它是通过调用
\u beginthread()
函数创建的。在线程内部,我将一些值推送到deque,由shared_ptr指向。这些值被正确地弹出到外部对象,因此一切似乎又正常了

当线程完成它的工作时,params结构从堆中删除,ref计数器递减(一切又恢复正常)。但当调用创建此共享_ptr的外部对象的析构函数时,refs计数器将递减并等于0,因此实际调用了指向对象的析构函数,并出现调试断言失败。失败的表达式是_pFirstBlock==pHead(双重删除?)。但我在VS2012的数据断点的帮助下进行了检查,
shared\u ptr.\u Rep.\u使用的地址
仅在我上面描述的时刻被访问

还有一点需要注意的是:如果没有任何东西推送到这个deque中,那么所有析构函数都会成功运行。 我做错了什么

typedef std::deque<MsgBuf_ptr> MsgQueue;
typedef std::tr1::shared_ptr<MsgQueue> MsgQueue_ptr;
typedef const MsgQueue_ptr& MsgQueue_ptr_p;
线程参数结构:

struct ThreadServerParam {  
    HANDLE ghStopEvent;
    MsgQueue_ptr qMsgQueue; 
    HANDLE ghMutex;
};
线程创建:

...
MsgQueue_ptr qMsgQueue;
...
qMsgQueue.reset(new MsgQueue)
...
bool bStartOK = start(qMsgQueue, ghMutex);  
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) {...}
}
线程函数:

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;
 }

除非您想修改指针,否则将指针作为引用传递是毫无意义的(可能是双关语),智能指针也是如此。这只是编译器要处理的又一个间接层次。当然,我说的是
start
函数中的
qMsgQueue
参数。@JoachimPileborg通过引用传递
std::shared\u ptr
可以防止增加
std::shared\u ptr
的内部引用计数器的轻微开销。虽然这可能不会对性能产生太大的影响,但在一些紧循环或代码的关键部分,这可能会产生影响。无论如何,使用或不使用“按引用传递”不会对我的问题产生影响:)我在这段代码中没有看到refcount问题,除非
MsgQueue\u ptr\p
中的
const
阻止其副本增加refcount。使用更完整的C++11,使用
std::shared\u ptr
而不是tr1变量和
std::thread
而不是
\u beginthread
是否有帮助?是否强制执行已创建线程和主线程的销毁顺序?如果没有,那么他们两个都可能试图删除shared_ptr指向的对象,因为他们两个都看到ref递减为0,并负责删除。