0

マルチスレッドをテストするプログラムを作成します。main関数で aがthread t作成されます。function Dにある では、thread t2 つのスレッドtttttが作成されます。関数Processは で実行されthread tttます。のProcessメンバー関数で呼び出されます。メンバー関数で呼び出されます。doAnotherThingclass Datthread ttdoOneThing

このプログラムをデバッグすると、エラーが発生しました。An exception (first chance) at 0x76f6f9d2 in Boost_Mutex.exe: 0xC0000008: An invalid handle was specified.

上記のエラーの代わりに、 次のエラーが発生する場合がありました。

Run-Time Check Failure #2 - Stack around the variable 'oDat' was corrupted.

この問題を解決してコードを変更するのを手伝ってくれる人はいますか?

これらは私のコードです:

「ダット」

#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();
}

私の質問のこの文に提案がある場合は、教えてください。修正します。ありがとうございました

4

1 に答える 1

3

ここでの主な問題は次の行です。

boost::thread ttt(Process, (void*)&pParam);

のアドレスpParam(既にポインターである) を取得して、 を生成しvoid**、それを にキャストし直しvoid*ます。C++ スレッド インターフェイスはタイプ セーフです。キャストしなければならないという事実は、何か間違ったことをしているという強力な指標です。(また、void*あらゆる場所での使用法。これは C スレッド インターフェイスに必要ですが、C++ には必要ありません。)

とにかく、Process次に を指すパラメータを取得し、それがオブジェクトpParamを指すふりをしpParaます。(pとにかくプレフィックスが付いているのはなぜですか? これはポインターではありません!) 次に、ポインターに到達しpDatますが、これはもちろんナンセンスParameterです。そもそもそこに構造体がないからです。したがって、取得したポインターは有効ではなく、有効なDat構造体を指していません。つまり、mutexそこにある も有効ではないことを意味します。つまり、内部スレッド ハンドルが無効であるため、最終的にクラッシュが発生します。ミューテックスをロックしようとするときに必要です。

コードを修正する方法は次のとおりです。すべての void ポインターを取り除き、すべてのキャストを取り除きます。また、厳密には必要ありませんが、変数の接頭辞も削除する必要があります。冗長な命名規則は十分に悪いものですが、誤って適用された冗長な命名規則は災害です。

もう 1 つエラーがあります。ミューテックスを使用してすべてのアクセスを保護するのではなく、1 つだけです。xこれは無駄です。あなたはまだ競合状態を持っています。共有変数へのすべてのアクセスを保護する必要があります。また、手動でandlock_guardを呼び出す代わりに RAII オブジェクトを使用して、ロックを解除することを決して忘れないようにする必要があります。lockunlock

于 2015-08-25T08:06:12.340 に答える