Search code examples
c++multithreadingboostboost-mutex

Error : An exception (first chance) at 0x76f6f9d2 in Boost_Mutex.exe: 0xC0000008: An invalid handle was specified


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


Solution

  • 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.