I write a program to test multithreading. In main function a thread t is created. In function D, which is in thread t, two threads tt and ttt will be created. The function Process runs in thread ttt . In Process a member function doAnotherThing of class Dat will be called. In thread tt a member function doOneThing will be called.
When I debug this program, an error occured: An exception (first chance) at 0x76f6f9d2 in Boost_Mutex.exe: 0xC0000008: An invalid handle was specified.
Sometimes this error occured instead of the error above :
Run-Time Check Failure #2 - Stack around the variable 'oDat' was corrupted.
Can anyone help me to solve this Problem and modify the codes?
These are my codes:
"Dat.h"
#pragma once
#ifndef DAT_H
#define DAT_H
#include <boost\thread\thread.hpp>
using namespace std;
class Dat
{
public:
Dat();
~Dat();
void doOneThing();
void doAnotherThing ();
private:
boost::mutex omutex;
int x;
};
#endif // DAT_H
"Dat.cpp"
#include "Dat.h"
Dat::Dat()
{
}
Dat::~Dat()
{
}
void Dat::doOneThing()
{
x = 1;
}
void Dat::doAnotherThing()
{
omutex.lock();
x = 2;
omutex.unlock();
}
"main.cpp"
#include "Dat.h"
#include <boost\function.hpp>
struct Parameter // the Parameters of function Process and D
{
Dat* pDat;
};
void Process(void*pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
pUserParams->pDat->doAnotherThing();
}
void D(void* pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
boost::function<void()> f;
boost::thread ttt(Process, (void*)&pParam);
f = boost::bind(&Dat::doOneThing, pUserParams->pDat);
// the capture thread will be started
boost::thread tt(f);
ttt.join();
tt.join();
}
void main()
{
Dat oDat;
parameter pPara ;
pPara.pDat = &oDat;
boost::thread t(D,(void*)&pPara);
t.join();
}
If you have suggestions to this statement of my quesion, pleas tell me and i will modify it. Thank you
The main problem here is this line:
You take the address of
pParam(which is already a pointer), yielding avoid**, and then cast it back to avoid*. The C++ threading interface is type-safe. The fact that you have to cast is a strong indicator that you're doing something wrong. (Also, your usage ofvoid*all over the place. This is needed for C threading interfaces, but not for C++.)Anyway, in
Processyou then take the parameter, which points topParam, and pretend that it points to yourpParaobject. (Why is that prefixedpanyway? It's not a pointer!) Then you reach into it to thepDatpointer, which is of course nonsense, because there's noParameterstruct there in the first place. So the pointer you get isn't valid, and doesn't point to a validDatstruct, which means that themutexin there isn't valid either, which means its internal thread handle isn't valid, so you finally get the crash you need when you try to lock the mutex.Here's how you fix your code: get rid of all void pointer and get rid of all casts. Also, which not strictly necessary, you should also get rid of the variable prefixes. A redundant naming convention is bad enough, but an incorrectly applied redundant naming convention is a disaster.
You have one more error: you don't protect all your accesses to
xwith the mutex, just one. This is useless. You've still got the race condition. You have to protect all accesses to a shared variable. Also, you should use alock_guardRAII object instead of manually callinglockandunlock, so that you can never forget to unlock.