2017-01-18 21 views
1

私は内部ライブラリを制御したり知っていない外部ライブラリを使用しています(proprietarycallbacksと呼ぶことができます)。異なるバージョンでコンパイルされた同じコードは異なる結果を提供します

私は私は2つのブール変数を持つクラスと呼ばれるコールバックしていることを知っている:そして、私は、コールバッククラスから継承する別のクラス持っ

class callbacks : public proprietarycallbacks { 
    bool a = false; 
    bool b = false; 
    virtual callbackHandler() { 
    cout "callback received\n"; 
    b = true; 
    } 
} 

を:

class MyObject : public callbacks { 

    void test() { 
    while (!b) { 
     cout << "test " << a << " " << b << endl; 
     usleep(100000); 
    } 
    } 
} 

をこのコードはで正しくコンパイル2つの異なるGCCバージョンとLIBCバージョンの2つの異なるLinuxバージョン。

最新のもの(linux mint、GCC 5.4 LIBC 2.23)で、私はこのアプリケーションを実行します.coutを参照してください。コールバックが呼び出されると、そのコードはその間存在します。

古いもの(debian、GCC 4.9.2、LIBC 2.19)では、whileは決して存在しません。コールバックの中からプリントを見ることはできますが、変数は常にfalseです。

私はコードと変数の継承を構成する方法に何か問題がありますか、これは私が使用しているソフトウェアのバージョンと関係がありますか?

は、それが関与する複数の実行スレッドがあることをごtest()方法から明らかなお時間を

+0

'b'の設定と' a'のテストはタイプミスですか?同じスレッド上のコールバックとループもですか? –

+0

変数を 'std :: atomic_bool'に変更すると、その違いは消えますか? –

+0

(前述のtypoが実際にはタイプミスであると仮定します) 'test()'と 'callbackHandler()'が別のスレッドから呼び出されたとすると、 'a'への同時読み書きを行います。期待どおりに動作することは保証されません。提案されているように 'std :: atomic_bool'で何が起こるかを知ることができます。単に' a'を 'volatile'と宣言するだけでも可能です。 1つのコンパイラバージョンが、ループ内で「a」が変化していないと判断し、それをループから読み続けることは非常に可能性があります。メモリの代わりにレジスタ。 – jdehesa

答えて

0

、ありがとうございました。 test()は1つの実行スレッド内にあり、コールバックは他の実行スレッドによって呼び出されます。

boolフラグを他の実行スレッドに設定し、test()実行スレッド内の同じフラグを読み取ることは、互いに順序付けされません。

通常の解決策は、std::atomic_boolを使用することです。シーケンシングを実装し、変数をアクセスして1つの実行スレッドに設定するか、または他の実行スレッドで現在の値を読み取るために、std::mutexを使用してください。

+0

あなたはもっと黙想できますか?私は、ミューテックスの欠如は、変数が変更されている間に不正な値で変数を読み取ることができるということに同意します。それにもかかわらず、次の反復では、読み込みに更新された値があってはいけませんか? – BlunT

+0

@BlunT:どうしてですか? – Malkocoglu

+0

書き込みが行われている間に読み込みが行われると、読み込まれる値が正しくないことがわかります。しかし、その後の読み取りでは、その間に更新されたオブジェクトから値を取り出すべきではないでしょうか?それでなぜ?値は未定義の時間キャッシュされていますか? – BlunT

関連する問題