2

WindowsXPでMinGW4.6.2を使用していますが、std::atomicで奇妙な動作が発生しました。状況は次のとおりです。

  • スレッドAは、std :: atomic変数を作成します(テンプレートパラメーターとしてT *を使用)。
  • スレッドBはそれを変更します。
  • スレッドAは変更を待ってから、変数を読み取ります。

最終的に、スレッドAによって読み取られた値は、スレッドBによって設定された値ではありません。

std :: atomicを削除すると(つまり、変数をポインターとして保存すると)、期待どおりに機能します。さらに興味深いことに、テンプレートパラメーターをunsigned longに設定し、ポインターをT *との間でキャストすると、期待どおりに機能します。

代入演算子を使用して値を設定し、ロードメンバーを使用して値を取得しています。

パラメータとしてT*を使用したstd::atomicがどのように機能するかがわかりませんか、それともこの動作が壊れていますか?

編集

いくつかのコード

    #include <boost/thread.hpp>
    #include <atomic>

    using namespace std;

    void* vptr;
    std::atomic<unsigned int> aui;
    std::atomic<void*> aptr;

    void foo()
    {
        vptr = (void*) 0x123;
        aui = (unsigned int) 0x123;
        aptr = (void*) 0x123;
    }

    int main(int argc, char* argv[])
    {
        boost::thread threadA;

        vptr = nullptr;
        aui = 0;
        aptr = nullptr;

        threadA = boost::thread(foo);
        threadA.join();

        cout << vptr << " " << (void*)aui.load() << " " << aptr.load();

        return 0;
    }

出力は次のとおりです:0x123 0x123 0x41d028

4

2 に答える 2

2

MinGW 4.6.1で問題を再現しました(4.7.0で修正されました)。lib/gcc/mingw32/4.6.2/include/c++/bits/atomic_0.h問題を修正した新しいMinGWに移動できない場合は、次のようにマクロのヘッダーの定義にパッチを適用できるはずです_ATOMIC_STORE_(4.6.2のヘッダーが4.6.1と十分に類似していると仮定します)。

#if 0 /* disable the original broken macro */
#define _ATOMIC_STORE_(__a, __n, __x)                      \
  ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
    __i_type* __p = &_ATOMIC_MEMBER_;                      \
    __typeof__(__n) __w = (__n);                           \
    __atomic_flag_base* __g = __atomic_flag_for_address(__p);          \
    __atomic_flag_wait_explicit(__g, __x);                 \
    *__p = __w;                                \
    atomic_flag_clear_explicit(__g, __x);                      \
    __w; })
#else
#define _ATOMIC_STORE_(__a, __n, __x)                      \
  ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
    __i_type* __pxx = &_ATOMIC_MEMBER_;                    \
    __typeof__(__n) __w = (__n);                           \
    __atomic_flag_base* __g = __atomic_flag_for_address(__pxx);        \
    __atomic_flag_wait_explicit(__g, __x);                 \
    *__pxx = __w;                                  \
    atomic_flag_clear_explicit(__g, __x);                      \
    __w; })
#endif

問題は、という名前のマクロ内のローカル変数にあるようです。これは、マクロパラメータに対して__pも名前が付けられた変数を使用してマクロを呼び出すと、明らかに混乱を引き起こします。に展開されると、呼び出し元が「渡した」変数にアクセスする代わりに、展開されたマクロがローカル変数にアクセスします。__p__n__n__p

于 2012-10-18T22:31:43.420 に答える
0

これはhttp://gcc.gnu.org/bugzilla/show_bug.cgi?id=51811である可能性があります-これはGCC4.7で修正されています

問題の原因となるコードを表示できますか?

于 2012-10-18T16:47:09.810 に答える