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
Process
you then take the parameter, which points topParam
, and pretend that it points to yourpPara
object. (Why is that prefixedp
anyway? It's not a pointer!) Then you reach into it to thepDat
pointer, which is of course nonsense, because there's noParameter
struct there in the first place. So the pointer you get isn't valid, and doesn't point to a validDat
struct, which means that themutex
in 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
x
with 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_guard
RAII object instead of manually callinglock
andunlock
, so that you can never forget to unlock.