考虑以下代码片段:
unsigned global;
while(global);
在一个由IRQ调用的函数中,修改了global
变量。然而,g++编译器移除了“是否不为零”的测试,并将while循环转换成无限循环。
禁用编译器优化可以解决问题,但C++是否提供了一种语言构造来解决这个问题呢?
考虑以下代码片段:
unsigned global;
while(global);
在一个由IRQ调用的函数中,修改了global
变量。然而,g++编译器移除了“是否不为零”的测试,并将while循环转换成无限循环。
禁用编译器优化可以解决问题,但C++是否提供了一种语言构造来解决这个问题呢?
将变量声明为volatile
:
volatile unsigned global;
这个关键字告诉编译器 global
可以在不同的线程中修改,所有的优化都应该被关闭。
global = 5 + 6;
中,您的语句可能暗示着5 + 6
没有被简化。 - Sebastian Mach由于您正在使用GCC并且您说使变量volatile
不起作用,因此您可以通过欺骗编译器来让优化器认为循环改变了变量:
while(global)
asm volatile("" : "+g"(global));
这是一个内联汇编语句,它表示它修改了变量(作为输入输出操作数传递)。但它是空的,所以在运行时显然不会执行任何操作。尽管如此,优化器认为它修改了变量 - 程序员这么说,而编译器除了操作数替换(即简单地用另一个文本替换一个文本)之外,实际上并不关心内联汇编的主体,并且不会对其进行任何有趣的操作。
由于主体为空且使用的约束是可用的最通用约束,因此它应该可靠地在所有支持GCC内联汇编的平台上工作。