为什么我的变量没有更新?

Zac*_*ack 6 c embedded debugging

我已经定义了一个具有初始值的变量.
单步执行代码时:

  • 我可以看到初始值
  • 我的函数改变了值
  • 当我稍后使用该变量时,它具有错误的值

怎么了?

注意:这是针对常见问题的参考问题.如果此处的通用答案对您没有帮助,请发布包含完整实际代码的问题.

Zac*_*ack 15

变量可能无法保留值的原因有多种.虽然有些是神秘且难以调试的,但一些最常见的原因包括:

变量由中断修改

//---in main()---
unint8_t rxByte = 0;
printf("%d", rxByte);   //prints "0"

//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG;       //rxByte set to (for example) 55

//---later in main()---
printf("%d", rxByte);   //still prints "0"!!!
Run Code Online (Sandbox Code Playgroud)

如果变量被中断处理程序修改,则需要将其声明为volatile.Volatile让编译器知道变量可以异步修改,并且不应该在寄存器中使用缓存副本.

//---in main()---
volatile unint8_t rxByte = 0;
printf("%d", rxByte);   //prints "0"

//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG;       //rxByte set to 55

//---later in main()---
printf("%d", rxByte);   //corectly prints 55
Run Code Online (Sandbox Code Playgroud)

超越数组的界限

C中没有检查可以防止超出数组的范围.

int array[10];
int my_var = 55;

printf("%d", my_var);   //prints "55"
for(i=0; i<11; i++)   // eleven is one too many indexes for this array
{
  array[i] = i;
}
printf("%d", my_var);   // prints "11"!!!
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们循环11次,这是一个比数组大的索引.在大多数编译器中,这将导致覆盖在数组之后声明的变量(页面上的任何地方,甚至不必在下一行声明它们).这种情况可能发生在许多不同的情况下,包括多维数组和堆栈损坏.

忘记取消引用指针

虽然微不足道,但在进行赋值时忘记指针上的星号不会正确设置变量

int* pCount;
pCount = 10;   //forgot the asterisk!!!
printf("%d", *pCount);   //prints ??
Run Code Online (Sandbox Code Playgroud)

屏蔽具有相同名称的变量

在内部作用域中重用变量名称(如if/for/while块内部或函数内部)会在其他位置隐藏具有相同名称的变量.

int count = 10;   //count is 10
if(byteRecevied)
{
  int count = U0RXREG;   //count redeclared!!!
  DoSomething(count); 
  printf("%d", count);   //prints "55"
}
printf("%d", count);   //prints "10"
Run Code Online (Sandbox Code Playgroud)


Roc*_*net 7

我想为Zack的优秀答案添加另一个可能的原因.

优化

这个经常给我带来惊喜.一个好的优化编译器会注意到两个不同的变量从不同时使用,并且会通过在内存中为这些变量提供相同的地址优化程序.当您单步执行代码时,您可能会在监视窗口中看到一个明显发生变化的变量.但真正发生的是共享其地址的变量正在被写入.

编译器提取的另一个技巧就是摆脱它所实现的变量是不必要的.有时你可能在代码中做了相同的事情:

force_a = mass_a * acceleration_a
force_b = mass_b * acceleration_b
total_force = force_a + force_b
Run Code Online (Sandbox Code Playgroud)

编译器发现没有真正需要变量force_aforce_b,因此将代码更改为:

total_force = (mass_a * acceleration_a) + (mass_b * acceleration_b)
Run Code Online (Sandbox Code Playgroud)

你永远不会看到force_aforce_b是更新,但你仍然可以将它们添加到监视窗口.

当我单步执行程序时,我确信某个变量或其他变量具有错误值,但是当我让程序运行而没有步进时,它似乎有效.检查这是不是发生在你身上.

添加:

正如Ashish Kulkarni所说,你可以通过关闭优化来检查这一点.