【发布时间】:2017-01-18 13:43:18
【问题描述】:
我正在使用一个我无法控制也不知道其内部结构的外部库(我们称之为专有回调)。
我知道我有一个名为 callbacks 的类,它有两个 bool 变量:
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);
}
}
}
此代码在两个不同的 linux 版本中正确编译,有两个不同的 GCC 版本和 LIBC 版本。
在最近的一个(linux mint,GCC 5.4 LIBC 2.23)上,我运行应用程序,在 while 中查看 cout,当调用回调时,代码存在 while。
在较旧的版本(debian、GCC 4.9.2、LIBC 2.19)上,虽然从不存在,但变量始终为 false,即使我可以从回调内部看到打印。
我构建代码的方式和变量继承是否有问题,或者这与我使用的软件版本有关?
感谢您的宝贵时间
【问题讨论】:
-
b的设置和a的测试是不是错字?回调和循环也是在同一个线程上吗? -
如果你把变量改成
std::atomic_bool,区别会消失吗? -
(假设前面提到的错字实际上是一个错字)假设
test()和callbackHandler()是从不同的线程调用的,您将对a进行并发读写,其中,总之,不能保证按预期工作。您可以按照建议看到std::atomic_bool发生了什么,甚至只是将a声明为volatile;很可能一个编译器版本决定a在循环中没有改变并继续从例如一个寄存器而不是内存。 -
@jdehesa
volatile不是用来解决线程问题的。 -
@RichardCritten 是的,但我认为在这种情况下它会产生足够的差异,让两个编译器生成的程序行为相似(并揭示为什么以前不是这种情况)。当然,对于实际应用来说,这可能还不够。