未操作的变量值自动修改--强制类型转换导致变量覆盖

来源:互联网 发布:淘宝什么值得买 编辑:程序博客网 时间:2024/05/17 08:21

最近在软件调试过程中遇到一个很奇怪的问题,最终查明的原因是函数内部一个局部变量在被函数调用(值传递而非地址传递)之后,变量莫名被修改,导致程序运行异常。

我把问题代码提炼如下:

// 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)强制类型转换时,数据截断一般是安全的,但数据扩展应当注意变量覆盖问题。