未操作的变量值自动修改--强制类型转换导致变量覆盖
程序员文章站
2022-05-15 09:51:03
...
最近在软件调试过程中遇到一个很奇怪的问题,最终查明的原因是函数内部一个局部变量在被函数调用(值传递而非地址传递)之后,变量莫名被修改,导致程序运行异常。
我把问题代码提炼如下:
// test_enum.cpp : 定义控制台应用程序的入口点。
#include <stdio.h>
#include <stdlib.h>
#define uint32_t unsigned int
#define uint16_t unsigned short int
#define uint8_t unsigned char
typedef enum boolean_e
{
RET_FALSE = 0 ,
RET_TRUE
} boolean_t;
int dba_proc_stat_get(uint8_t olt_id, boolean_t *bw_dn_table_sw_index_stat)
{
uint32_t data = 0;
data = olt_id & 0x11;
//*bw_dn_table_sw_index_stat = (boolean_t)(data & 0x1);
*bw_dn_table_sw_index_stat = (boolean_t)(data | 0x12345678);
return(0);
}
int main()
{
uint32_t olt_id = 4;
uint8_t bw_dn_table_sw_index_stat = 0xAA;
printf("%s: olt_id = %u\r\n", __FUNCTION__, olt_id);
dba_proc_stat_get(olt_id, &bw_dn_table_sw_index_stat);
printf("After add: olt_id = %u\r\n", olt_id);
printf("bw_dn_tables_set OK.\r\n");
return 0;
}
代码运行结果如图所示:
可以看到,无符号32位整型变量 olt_id 初始值为4,运行后,结果变为 18。
然后调试代码,找到 无符号32位整型变量 olt_id 和无符号8位整型变量bw_dn_table_sw_index_stat 的地址,确定他们之间有何联系:
olt_id 的地址 和 bw_dn_table_sw_index_stat 的地址如下:
可以看到 olt_id 和 bw_dn_table_sw_index_stat 的 地址相隔 3 个地址,打印从 0xbfffede4 开始的 8 个地址:
函数调用执行完后,olt_id 的 值确实发生了改变,变为 0x12345678 (小端模式),分析至此,原因豁然明朗:
枚举类型占用 4 个字节,在对 bw_dn_table_sw_index_stat 进行赋值时使用强制类型转换,导致从 0xbfffede5 开始后的 4 个字节数据被修改,而 olt_id 的地址刚好位于这一区间的最后一个字节地址: 0xbfffede8,于是 olt_id 被覆盖。
总结:
(1)枚举类型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,一般占用 4 个字节内存(依据不同的系统而定);
(2)强制类型转换时,数据截断一般是安全的,但数据扩展应当注意变量覆盖问题。
上一篇: 链接规则引发的全局变量的值被改变