如果我有:
__PRE__会
struct whatever {
int data;
};
volatile whatever test;不稳定? 我知道volatile通知编译器可能会更改值,但为了完成此功能,编译器是否需要引入内存栅栏才能使其工作?
根据我的理解,易失性对象的操作顺序不能重新排序,必须保留.这似乎暗示一些内存栅栏是必要的,并且没有真正解决方法.我说的是对的吗?
在这个相关问题上有一个有趣的讨论
...对于不同的volatile变量的访问不能由编译器重新排序,只要它们出现在单独的完整表达式中......对于线程安全而言volatile是无用的,但不是由于他给出的原因.这不是因为编译器可能会重新排序对易失性对象的访问,而是因为CPU可能会重新排序它们.原子操作和内存屏障阻止编译器和CPU重新排序
...从C++标准的角度来看,编译器执行某些操作与编译器发出导致硬件执行某些操作的指令之间没有区别.如果CPU可能重新排序对volatiles的访问,则标准不要求保留其订单....
... C++标准没有对重新排序有什么区别.你不能争辩说CPU可以重新排序它们没有可观察到的影响,所以没关系--C++标准将它们的顺序定义为可观察的.如果编译器生成的代码使平台能够满足标准要求,则编译器在平台上符合C++标准.如果标准要求对挥发物的访问不能重新排序,则重新排序它们的平台不符合要求....
我的观点是,如果C++标准禁止编译器重新排序对不同易失性的访问,理论上这种访问的顺序是程序可观察行为的一部分,那么它还要求编译器发出禁止CPU执行的代码所以.该标准没有区分编译器的作用以及编译器生成的代码使CPU执行的操作.
这确实产生了两个问题:它们中的任何一个是"正确的"吗?实际的实现到底做了什么?
在C/C++中使用volatile关键字有什么用?声明变量volatile与不声明变量之间有什么区别volatile?
具有空体的无限循环在C++ 11中具有未定义的行为.我不知道它是否也用C语言,所以让我说我在C++ 11中编写嵌入式固件(我知道,不太可能,但请耐心等待).
如果我main只是一个:
while (true) {}
Run Code Online (Sandbox Code Playgroud)
并且设备的其余功能由中断处理,我可以采取哪些方法来发现我的实现是否使这个循环安全且有意义?请记住,根据标准,在这种情况下,实现可以随意执行任何操作,包括完全删除循环.
假设在实现的文档中没有明确说明,因为我从未见过它.
或者这是一个失败的原因,我应该破解一个解决方法?
volatile unsigned int dummy = 0;
while (true) {
// Make the loop well-defined...
dummy++;
// ...with a trivial operation that'll hardly ever even happen
sleep(42*86400);
}
Run Code Online (Sandbox Code Playgroud)
我认识到嵌入式开发人员在历史上并没有过多地考虑这种事情,而是从他们的编译器中采用更"脚踏实地","常识"的方法.但我更倾向于严格按照标准编码,以尽可能避免意外.
我在我的Java程序的main方法中运行了一个while循环.循环应该运行,直到在程序的keyPressed方法中将布尔标志变量设置为true(我将程序作为KeyListener添加到JFrame).
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class ThreadWhile implements KeyListener {
private boolean flag = false;
public static void main(String[] args) {
//Set up key listening on a dummy JFrame
JFrame frame = new JFrame("Key Detector 9000");
frame.setVisible(true);
ThreadWhile tw = new ThreadWhile();
frame.addKeyListener(tw);
System.out.println("Looping until flag becomes true...");
while(!tw.flag) {
//Commenting the println out makes the loop run forever!
System.out.println(tw.flag);
}
System.out.println("Flag is true, so loop terminated.");
System.exit(0);
}
public void keyPressed(KeyEvent e) {
flag = true; …Run Code Online (Sandbox Code Playgroud) 我有一个int foo从两个线程访问的变量.假设我没有竞争条件问题(访问受到互斥锁的保护,所有操作都是原子的,或者其它任何方法都可以防止竞争条件),仍然存在"寄存器缓存"的问题(缺少更好的名称) ,编译器可能会认为如果变量被读取两次而没有在两者之间写入,则它是相同的值,因此可以"优化"诸如以下内容:
while(foo) { // <-may be optimized to if(foo) while(1)
do-something-that-doesn't-involve-foo;
}
Run Code Online (Sandbox Code Playgroud)
要么
if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label;
do-something-that-doesn't-involve-foo;
do-something-else-that-doesn't-involve-foo;
if(foo) // <-may be optimized to jz label2;
do-something;
Run Code Online (Sandbox Code Playgroud)
并标记foo为volatile解决这个问题?是否保证一个线程的更改到达另一个线程?
如果没有,还有什么方法可以做到这一点?我需要一个Linux/Windows解决方案(可能是单独的解决方案),没有C++ 11.
我正在用C++/Qt开发一个简单的应用程序,我有以下声明:
QGridLayout *layout = new QGridLayout;
我正在使用gdb调试应用程序.我设置了一个断点,它运行正常,调试器就行了.但是,如果我尝试检查上面声明的对象,我得到这个输出:
Run Code Online (Sandbox Code Playgroud)-data-evaluate-expression --thread 1 --frame 0 layout ^done,value="<value> optimized out>"
我读到这条消息,"<value> optimized out>"是因为编译器对代码进行了优化,并将数据放入寄存器中.我正在使用g ++编译器,设置了flag -O0(无优化).
是否存在我缺少的东西,或者它是否存在一种声明变量不被优化的方式,比如存储说明符register?我在Ubuntu 10.10 Maverick,内核2.6.35-24.
EDIT1
更多代码:
WorkspaceChooserDialog::WorkspaceChooserDialog(QWidget *parent) : QDialog(parent)
{
setWindowTitle(tr("Select a workspace location"));
QLabel *wpLabel = new QLabel(tr("Workspace:"), this);
QLineEdit *wpLineEdit = new QLineEdit(QDir().homePath(), this);
QPushButton *okButton = new QPushButton(tr("OK"), this);
QPushButton *cancelButton = new QPushButton(tr("Cancel"), this);
QGridLayout *layout = new QGridLayout;
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(cancelButton, …Run Code Online (Sandbox Code Playgroud) c++ ×7
volatile ×4
c ×3
c++11 ×2
c++-faq ×1
declaration ×1
gdb ×1
java ×1
optimization ×1
while-loop ×1