考虑以下代码:
unsigned global;
while(global);
global
在由IRQ调用的函数中被修改。但是,g ++删除了" is-not-zero"测试并将while循环转换为无限循环。
禁用编译器优化可以解决问题,但C ++是否为它提供了语言结构?
答案 0 :(得分:17)
将变量声明为volatile
:
volatile unsigned global;
这是一个关键字,它告诉编译器可以在不同的线程中修改global
,并且应该关闭所有优化。
答案 1 :(得分:8)
由于您正在使用GCC并且您说使变量volatile
不起作用,您可以欺骗优化器认为循环通过向编译器说明来更改变量:
while(global)
asm volatile("" : "+g"(global));
这是一个内联汇编语句,它声明它修改变量(它作为输入输出操作数传递)。但它是空的,所以显然它在运行时没有做任何事情。尽管如此,优化器认为它修改了变量 - 程序员这样说,并且编译器禁止操作数替换(这意味着简单地用另一个替换一个文本),并不真正关心内联汇编的主体而不会做任何有趣的事情。
因为主体是空的,并且约束使用了最常用的主体,它应该在GCC支持内联汇编的所有平台上可靠地工作。
答案 2 :(得分:2)
您可以在函数声明中使用GCC属性来禁用基于每个函数的优化:
void myfunc() __attribute__((optimize(0)));
有关详细信息,请参阅GCC Function Attributes页面。