4

我在 C++ 中有以下循环,用 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);
}

注意 logStatus() 是按值接收其参数的,所以参数不会被修改。m_firstOk 和 m_secondOk 当然是 bool 成员属性。

到目前为止,这一切都很好。我收到了一份报告,它没有检测到 firstOk 何时更改。我使用 gdb 附加到正在运行的进程。它在 sleep() 行中,当我看到以下内容时我感到很惊讶:

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

怎么回事?当 firstOk 应该是按位与 0x1 的结果时,它怎么可能是 244?我知道一个布尔值实际上存储为一个整数,但我的按位 AND 怎么能被忽略呢?由于它是 244,当它应该为假时,它被评估为真,这就是问题的原因。

不是将按位与的结果分配给布尔安全吗?这是一个 gcc 错误吗?或者我应该做如下的事情?

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

提前致谢。

4

3 回答 3

2

当您到达调用时,局部变量firstOksecondOk不是“活动的” sleep(),因此即使它们被分配堆栈槽,它们的值也完全有可能(而且确实很有可能)不再存储在任何地方。

如果您需要调试这些变量中的任何一个,则需要

  1. 将它们重新声明为static,这会将它们分配出堆栈的持久存储
  2. firstOk将and的声明移动secondOk到外部范围。(注意,这可能还不够,除非您将它们移出文件范围。)
  3. firstOk将和的值复制secondOk到持久变量或存在于外部范围中的变量,并检查它们。

无论如何,一旦您完成调试过程,我将恢复上述任何调试措施。:-)

至于您的最后一个问题,该语句bool firstOk = status & 0x1非常好,它后面的语句设置secondOk. 将 an 分配int给 abool会将零/非零值强制为falsetrue

至于你的实际错误(不知何故你错过了一个过渡firstOk),我看不出你可能在这段代码中丢失了它。这部分代码看起来不错。您的getStatus()函数是否可能需要比每秒一次更频繁地调用?其他东西可以写到m_firstOkorm_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 回答