0

私の関数が行うことは、ブール値の配列を反復処理し、false に設定された要素を見つけると、true に設定されます。この関数は、メモリへのポインターを返すメモリ マネージャー シングルトン クラスのメソッドです。複数のスレッドが関数を呼び出しているため、イテレータがループしているように見え、最初から開始するというエラーが発生します。

void* CNetworkMemoryManager::GetMemory()
{
        WaitForSingleObject(hMutexCounter, INFINITE);

    if(mCounter >= NetConsts::kNumMemorySlots)
    {
       mCounter = 0;
    }

    unsigned int tempCounter = mCounter;

    unsigned int start = tempCounter;

    while(mUsedSlots[tempCounter])
    {
        tempCounter++;

        if(tempCounter >= NetConsts::kNumMemorySlots)
        {
            tempCounter = 0;
        }

        //looped all the way around
        if(tempCounter == start)
        {
            assert(false);
            return NULL;
        }
    }

    //return pointer to free space and increment

    mCounter = tempCounter + 1;
        ReleaseMutex(hMutexCounter);

    mUsedSlots[tempCounter] = true;
    return mPointers[tempCounter];
}

私のエラーは、ループでオフになるアサートです。私の質問は、関数を修正する方法と、マルチスレッドが原因のエラーですか?

編集: mCounter 変数を保護するためにミューテックスを追加しました。変化なし。エラーは引き続き発生します。

4

1 に答える 1

1

エラーの原因がマルチスレッドかどうかはわかりませんが、コードがスレッドセーフではないと言えます。

でロックを解放します

ReleaseMutex(hMutexCounter);

次に、tempCounter と mUsedSlots にアクセスします。

mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];

どちらも const ではありません。これらの変数へのアクセスを正しくシリアル化していないため、これはデータ競合です。

これを次のように変更します。

mUsedSlots[tempCounter] = true;
const unsigned int retVal = mPointers[tempCounter];
ReleaseMutex(hMutexCounter);
return retVal;

次に、少なくともコードはスレッドセーフです。これで問題が解決するかどうかはわかりませんが、試してみてください。複数のコアを持つマシンでは、データ競合の結果として非常に奇妙なことが起こります。

std::mutex一般的なベスト プラクティスとして、や などの C++11 同期機能std::lock_guardを確認することをお勧めします。うっかりして早すぎることはできません。これにより、コードの移植性も向上します。C++11 をまだ持っていない場合は、同等のブーストを使用してください。

于 2013-02-18T17:30:20.137 に答える