这是我的代码:
volatile uint32_t value = *((volatile uint32_t *) 0xA0000000); // here `value` is 12498
value *= 2; // here `value` is still 12498
value |= 0x0000001; // still 12498
在我的调试器中分析变量value
时,它在所有行上保持相同的值。我做错了什么?
答案 0 :(得分:5)
也许你的调试器实际上并不那么好。当我的某个工具似乎没有表现时,我总是会对另一个工具进行检查。
尝试使用以下方法调试老式方法:
volatile uint32_t value = *((volatile uint32_t *) 0xA0000000);
printf ("A:%d\n", value);
value *= 2;
printf ("B:%d\n", value);
value |= 0x0000001;
printf ("C:%d\n", value);
或其他一些输出方法如果printf
不可用(看起来您可能在嵌入式空间中工作)。
看看你得到了什么 - 我更倾向于信任printf
- 调试而不是调试器。
如果您的问题不在value
,而在位置0xA0000000
的内存中,那么它就会按预期运行。
您正在操纵局部变量,而不是内存位置。您需要将值写回来,例如:
*((volatile uint32_t *) 0xA0000000) = value;
但是,考虑到你使用volatile,你完全可能只需要一个变量指针到那个位置,以便更改立即反映出来。
如果是这种情况,你需要的是:
volatile uint32_t *pValue = (volatile uint32_t *) 0xA0000000;
*pValue *= 2;
*pValue |= 0x00000001;
在这种情况下,内存位置将在每条指令处更改,而不必显式写入值。
答案 1 :(得分:1)
value
是一个自动变量,其地址永远不会被占用,因此实际上忽略了它的易变性这一事实,因为它碰巧知道它运行的架构on,并得出结论,即使标准认为这是可观察的,一致性程序也无法观察到它的读写顺序。显然,这对调试器来说并不是很友好,但如果它发生的话,我也不会感到惊讶。实际上,编译器会假设你不能“看到”堆栈,如果你使用调试器,检查核心转储,将堆栈标记为只读并处理结果信号等,这是错误的。检查反汇编,看看是否实际出现了乘数/移位和位集。答案 2 :(得分:0)
尝试将值写入另一个临时变量并检查该值。有时这会欺骗编译器/调试器做你想做的事情。 AFAIK,volatile告诉编译器始终读取该值,如果它永远不会读取,则不一定要保留它。