全局变量和静态的危险性在于它的访问权限暴露在整个项目中,可能由于某个C文件的某个函数的异常(数组越界访问,野指针等等),导致全局变量,静态变量有时候会莫名的被修改了,而且比较难追踪到.这一点在多线程编程中尤其需要注意 ,看以下代码运行结果:
#include <stdio.h>
int globalNum = 100;//全局变量
int gAddr_for_static = 0; //用来保存函数里的静态变量地址
void test_static_temp(){
static int value_static = 10;//局部静态变量
printf("<-> value_static,addr=%x,value=%d \n\n",&value_static,value_static);
gAddr_for_static = &value_static;
}
//通过指针修改任何全局变量!静态变量!
void SetGlobalValue(int address,int v){
int *pt;
pt= address;
*pt = v;
}
int main(void) {
test_static_temp();//从输出得到静态变量的地址
int addr = &globalNum;
printf("<1> 初始化全局变量globelNum=%d ,内存地址=%x \n\n" , globalNum,&globalNum);
SetGlobalValue(addr,1234);
printf("<2> 调用函数后globelNum=%d,内存地址=%x \n\n" , globalNum,&globalNum);
addr = gAddr_for_static;//每个编译器得到的地址不同
SetGlobalValue(addr,4567);
test_static_temp();
return 0;
}
用c-clang在线运行,在线工具,在线编译IDE_w3cschool在线IDE编译器可以快速测试运行结果 (https://www.dooccn.com/)
<-> value_static,addr=601038,value=10
<1> 初始化全局变量globelNum=100 ,内存地址=60103c
<2> 调用函数后globelNum=1234,内存地址=60103c
<-> value_static,addr=601038,value=4567
#include<stdio.h>
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint24_t unsigned int
#define uint32_t unsigned int
#define uint64_t unsigned long long
void print_var(int *value)
{
printf("value=%d,0x%x.\n",*value,*value);
}
void set_var_zero(int *value)
{
*value = 0;
}
void print_var_u8(uint8_t *value)
{
printf("value=%d,0x%x.\n",*value,*value);
}
uint8_t a = 0xfe;
uint16_t b = 0x1234;
int main()
{
printf("RAW: a=%x,b=%x.\n", a, b);
print_var(&a);
print_var_u8(&b);
set_var_zero(&a);
printf("NEW: a=%x,b=%x.\n", a, b);
return 0;
}
最后看看这段代码在实际运行中异常的分析过程:
int g_value = 0;
void func_thread()
{
if(g_value==0)
{
msleep(10); //maybe run 10ms
if(g_value!=0)
{
//理论上这里应该永远不会被执行!但是多线程情况下这个情况却有几率发生。
g_flag_test=1;
}
}
}