我在一个定期调用的函数中声明了一个静态变量。我知道将变量声明为静态变量可以使它在程序生命周期中有效,而无需再次声明它。当然,由于它是本地的,因此只能通过其功能进行修改。
奇怪的是调试代码,执行了该函数,在离开函数之前,我确保变量的值为0
。在下一个函数调用中,在执行函数的任何行之前,变量的值将增加256
。如果在离开函数之前变量的值为10
,则在下一次调用时它将变为266
。这种行为是持久的。
什么会导致局部静态变量的值在函数调用之间改变?
很遗憾,我无法提交可重现此问题的代码段。
答案 0 :(得分:3)
什么会导致局部静态变量的值在函数调用之间改变?
可能的原因是代码另一部分的错误已写入存储静态变量的内存位置。
看看这段代码:
void bar()
{
static char y[2];
y[0] = '4';
y[1] = '2';
printf("BAR y=%c%c location of y is %p\n", y[0], y[1], (void*)y);
y[2] = 0; // error! writing out of bounds
y[3] = 1; // error! writing out of bounds
}
void foo()
{
static uint16_t x = 0;
printf("FOO x=%"PRIu16" location of x is %p\n", x, (void*)&x);
++x;
}
int main( int argc, char **argv ){
foo();
foo();
foo();
foo();
foo();
bar();
foo();
return 0;
}
您会注意到函数bar
包含一个错误,即它的写入超出了为y
分配的内存。
在我的系统上运行此代码会给出:
FOO x=0 location of x is 0x100407002
FOO x=1 location of x is 0x100407002
FOO x=2 location of x is 0x100407002
FOO x=3 location of x is 0x100407002
FOO x=4 location of x is 0x100407002
BAR y=42 location of y is 0x100407000
FOO x=256 location of x is 0x100407002
^^^^^
oh dear, x has changed...
因此,在我的系统上,静态变量x
放在静态变量y
之后。因此,由于bar
中的错误,调用x
时bar
的值将被覆盖。
注意:在其他系统上,结果可能会不同。
因此建议是:在函数的两次调用之间执行的代码中查找缓冲区溢出。
答案 1 :(得分:2)
正如评论和其他答案所述,这绝对是一个错误,很可能是代码另一部分的缓冲区溢出。
要查找代码的时间和部分修改静态局部变量,可以使用内存断点(或数据断点)。开始调试,并在第一个函数调用上在变量的地址上为变量的大小设置一个内存断点。现在,当罪魁祸首代码修改了该内存区域(即您的静态变量)时,该代码将中断。
在Visual Studio中,我认为它称为数据断点。
gdb也具有watch
命令的此功能。查看操作方法:Can I set a breakpoint on 'memory access' in GDB?