我将包含shared_ptr
to 的params 结构std::deque
作为函数的输入参数传递,该结构将在新线程中工作。这个双端队列在外部对象上创建为公共字段。当我将 shared_ptr 保存到params
结构中时,shared_ptr 的引用数会增加,并且一切似乎都很好。
至于线程,它是在调用_beginthread()
函数的帮助下创建的。在线程内部,我将一些值推送到由 shared_ptr 指向的双端队列。这些值在外部对象上正确弹出,所以一切似乎又正常了。
当线程完成它的工作时,从堆中删除的参数结构和引用计数器递减(一切都很好)。但是当创建这个 shared_ptr 的外部对象的析构函数被调用时,refs 计数器被递减并等于 0,因此实际上调用了指向对象的析构函数,并且出现了调试断言失败。失败的表达式是 _pFirstBlock == pHead(双重删除?)。但是我在 VS2012 的数据断点的帮助下检查了,该地址shared_ptr._Rep._Uses
仅在我上面描述的时刻被访问。
还有一点需要注意:如果没有任何东西推入这个双端队列,那么所有的析构函数都会成功运行。我做错了什么?
typedef std::deque<MsgBuf_ptr> MsgQueue;
typedef std::tr1::shared_ptr<MsgQueue> MsgQueue_ptr;
typedef const MsgQueue_ptr& MsgQueue_ptr_p;
shared_ptr 创建:
...
MsgQueue_ptr qMsgQueue;
...
qMsgQueue.reset(new MsgQueue)
...
bool bStartOK = start(qMsgQueue, ghMutex);
线程参数结构:
struct ThreadServerParam {
HANDLE ghStopEvent;
MsgQueue_ptr qMsgQueue;
HANDLE 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;
}