4

I have the following loop in C++, compiled with g++ 4.1.2:

while(1) {
    int status = getStatus();
    bool firstOk = status & 0x1;
    bool secondOk = status & 0x2;
    if(firstOk != m_firstOk) {
        logStatus(1, firstOk);
        m_firstOk = firstOk;
    }
    if(secondOk != m_secondOk) {
        logStatus(2, secondOk);
        m_secondOk = secondOk;
    }

    sleep(1);
}

Note logStatus() receives its parameters by value, so the parameter is not modified. m_firstOk and m_secondOk are of course bool member attributes.

This was working fine until now. I received a report that it didn't detect when firstOk changed. I attached to the running process with gdb. It was in the sleep() line and I got astonished when I saw the following:

(gdb) p m_firstOk
$1 = true
(gdb) p m_secondOk
$2 = true
(gdb) p firstOk
$3 = 244

WTF? How can firstOk be 244 when it should be the result of a bitwise AND with 0x1? I know a boolean is in fact stored as an integer, but how could my bitwise AND be ignored? Since it's 244, it's being evaluated as true when it should be false, which is the cause of the problem.

Isn't assigning the result of a bitwise AND to a boolean safe? Is this a gcc bug? Or should I do something like the following?

bool firstOk = (status & 0x1) ? true : false;

Thanks in advance.

4

3 に答える 3

2

ローカル変数firstOkとは、呼び出しにsecondOk到達したときに「ライブ」ではないため、スタック スロットが割り当てられていたとしても、それらの値がどこにも格納されていない可能性は十分にあります (実際、その可能性は非常に高いです)。sleep()

これらの変数のいずれかをデバッグする必要がある場合は、次のいずれかを行う必要があります

  1. それらを として再宣言しますstatic。これにより、スタックから永続ストレージが割り当てられます
  2. firstOkandの宣言をsecondOk外側のスコープに移動します。(ファイル スコープに移動しない限り、これでは不十分な場合があることに注意してください。)
  3. 永続変数または外側のスコープに存在する変数の値firstOkと値をコピーし、それらを検査します。secondOk

いずれにせよ、デバッグ プロセスが完了したら、上記のデバッグ手段を元に戻します。:-)

あなたの最後の質問に関しては、ステートメントbool firstOk = status & 0x1は設定に続くステートメントと同様に、完全に問題ありませんsecondOkintを a に代入すると、およびboolにゼロ/非ゼロの値が強制されます。falsetrue

あなたの実際のバグ (どういうわけか の遷移を見逃したfirstOk) に関しては、このコードのどこでそれを失ったのかわかりません。コードのこの部分は問題ないようです。getStatus()関数を 1 秒に 1 回以上呼び出す必要がある可能性はありますか? m_firstOk他にorに書き込むことはできますかm_secondOk? それらの宣言は表示されていないため、おそらくこれらは外側のスコープに存在します。

于 2013-05-12T11:04:28.533 に答える
0

可能な唯一の方法は、次の場合です。

1) スタックが何らかの形で上書きされました。

2) スリープ行に到達すると、テンポラリの値はそれほど重要ではないため、コンパイラはそれを追跡しないため、メモリ スロットが別の目的で使用されている可能性があります。

最初は動作し、後で動作がおかしくなる場合は、コードのそのセクションのコンパイラ バグではない可能性が高くなります。

于 2013-02-15T17:06:29.743 に答える
-1

正しい割り当ては次のとおりです。

bool firstOk = (status & 0x1) == 0x01;

または一般的に:

bool flag = (value & mask) == mask;
于 2013-02-15T10:46:39.547 に答える