欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

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