shared_ptr
toを含む params 構造体std::deque
を関数の入力引数として渡します。これは新しいスレッドで機能します。この両端キューは、パブリック フィールドとして外部オブジェクトに作成されます。そして、shared_ptr をparams
構造体に保存すると、shared_ptr の参照数が増加し、すべて問題ないようです。
スレッドに関しては、呼び出し_beginthread()
関数を使用して作成されます。スレッド内で、shared_ptr が指すいくつかの値を deque にプッシュします。これらの値は外部オブジェクトで正しくポップされるため、すべてが再び問題ないように見えます。
スレッドが作業を終了すると、params 構造体がヒープから削除され、ref カウンターが減少します (すべて問題ありません)。しかし、この shared_ptr が作成された外部オブジェクトのデストラクタが呼び出されると、refs カウンターがデクリメントされて 0 になるため、実際にポイントされたオブジェクトのデストラクタが呼び出され、デバッグ アサーション エラーが表示されます。失敗した式は _pFirstBlock == pHead (二重削除?) です。しかし、VS2012 のデータ ブレークポイントの助けを借りて確認しました。そのアドレスは、shared_ptr._Rep._Uses
上記の瞬間にのみアクセスされます。
もう 1 つ注意: この両端キューに何もプッシュされない場合、すべてのデストラクタが正常に実行されます。私が間違っていることは何ですか?
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;
}