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:
boost::thread ttt(Process, (void*)&pParam);
You take the address of pParam
(which is already a pointer), yielding a void**
, and then cast it back to a void*
. 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 of void*
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 to pParam
, and pretend that it points to your pPara
object. (Why is that prefixed p
anyway? It's not a pointer!) Then you reach into it to the pDat
pointer, which is of course nonsense, because there's no Parameter
struct there in the first place. So the pointer you get isn't valid, and doesn't point to a valid Dat
struct, which means that the mutex
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 a lock_guard
RAII object instead of manually calling lock
and unlock
, so that you can never forget to unlock.