1

私は実際に大きな問題に直面しています: シングルトン クラスがあります。私のプログラムはマルチスレッド MFC であるため、シングルトンのコンストラクターは異なるスレッドから呼び出すことができます。シングルトン インスタンス ゲッター関数をミューテックスで囲み、デッドロックや複数の構造を回避しました。以下の意味する関数の呼び出しは、最初は直接失敗します。

関数は次のようになります (LOG_MSG マクロは、指定された文字列をログ ファイルに記録します)。

MyClass& MyClass::singleton ()
{
    LOG_MSG("MyClass::singleton -> jump in");

    static CMutex oInitMutex;
    try
    {
        CSingleLock oSingleLock((CSyncObject *) &oInitMutex, TRUE);
        LOG_MSG("!!! SINGLETON LOCK OKAY !!!");
        static MyClass oMyClassInstance;
        LOG_MSG("!!! SINGLETON CONSTRUCTION OKAY !!!");
        return oMyClassInstance;
    }
    catch(...)
    {
        CString excMsg("Unexpected exception by creating MyClass singleton instance!");
        LOG_MSG(excMsg);
        throw excMsg;
    }
}

シングルトンオブジェクトの構築は失敗しないことがわかりました(「!!! SINGLETON CONSTRUCTION OKAY !!!」というメッセージが表示されるため)。

ログ出力は次のように述べています。

09.04.2013 ;07:14:51:832;"MyClass::singleton -> jump in"
09.04.2013 ;07:14:51:841;"!!! SINGLETON LOCK OKAY !!!"
... (constructor logs => NOTHING unexpected in it!!! everything runs fine, as they must!!!)
09.04.2013 ;07:14:52:125;"!!! SINGLETON CONSTRUCTION OKAY !!!"
09.04.2013 ;07:14:52:170;"Unexpected exception by creating MyClass singleton instance!"

どういう意味ですか?returnステートメントが例外をスローするのはいつですか??? この問題を解決するのを手伝ってください...

4

2 に答える 2

6

これはあなたの特定の質問には答えませんが、それでも全体的な問題の解決策です.mutexはまったく必要ありません. C++11 標準 [stmt.dcl]§4 では、(static関数に対してローカルな変数について話す場合) 次のように指定されています。

変数の初期化中に制御が同時に宣言に入った場合、同時実行は初期化の完了を待ちます。88変数の初期化中に制御が宣言に再帰的に入る場合、動作は未定義です。

注記 88 は次のとおりです。

Note 88: 実装は、イニシャライザの実行にデッドロックを導入してはなりません。

つまり、コンパイラが同期を導入します。手動で行う必要はありません。

于 2013-04-09T06:49:18.350 に答える
1

解決:

私は問題を理解しました、それは簡単ではありませんでした。私のエラーから学ぶために、失敗の原因となったコードを共有します。

コンストラクターsscanfで、不適切な方法で関数呼び出しを使用します。

const char* sBuffer;
// some stuff here that fills the sBuffer up
sscanf(sBuffer, "%X %X %X %X", &tags_[0], &tags_[1], &tags_[2], &tags_[3]);

配列は、シングルトン クラスで次のように定義されました。

private:
    char tags_[4];

注意: データを書き込むことができる特定のタイプの変数を待機するフォーマット コード。たとえば、私の場合、tags_配列は文字の配列ではなく整数の配列である必要があります。シングルトン クラスは を格納する必要があるためtags_、2 番目、3 番目、4 番目の要素にインデックスを付けた後、sscanf関数はメモリの未定義の場所に書き込みます。静的クラスのデータについて何かが上書きされ、複数のインスタンス化が発生しますが、これは可能です。ミューテックスによって回避されますが、その場合、ミューテックス オブジェクトは上書きされます。(s)scanf に必要なタイプの詳細については、こちらこちらをご覧ください。

結論:

C関数/低レベル呼び出しの使用に注意してください。入力パラメーターには、値だけでなく型にも注意を払ってください。期待どおりに他の型をサポートすると、プログラムの動作は未定義になりますが、コンパイラ エラーは発生しません。後でその問題を見つけるのは非常に困難です。

于 2013-04-10T07:10:42.550 に答える