agile_modbus
agile_modbus copied to clipboard
[bug]在swtich的case中定义变量,导致指针指向该变量的地址被其他变量使用
在swtich的case中定义变量,导致指针指向该变量的地址被其他变量使用
运行环境
- 硬件:STM32F429IGT6单片机
- 操作系统:RTT 5.0.0
- 使用串口V2驱动:使用收发DMA
- 编译:KEIL AC6编译器
- 使用MODBUS RTU 从机功能
错误情况
- AC6编译器使用-O0优化,上位机进行线圈写入True成功。上位机发送成功,上位机发送读取该寄存器写入为True.
- AC6编译器使用-Oz优化,上位机进行线圈写入True失败。上位机发送成功,上位机发送读取该寄存器写入为False. 例如对线圈地址0X02写入True,读取回来还是FALSE。
错误原因
- data 变量在case中定义,在退出该case时,该地址已经被释放,导致该地址被其他变量使用,导致写入失败。
- slave_info.buf = (uint8_t *)&data;该代码使用挂钩data地址,退出case时,地址已被认为可以使用。
case AGILE_MODBUS_FC_WRITE_SINGLE_COIL: {
//! warning: comparison is always false due to limited range of data type [-Wtype-limits]
#if 0
if (address > 0xFFFF) {
exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS;
break;
}
#endif
int data = (req[offset + 3] << 8) + req[offset + 4];
if (data == 0xFF00 || data == 0x0)
data = data ? 1 : 0;
else {
exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE;
break;
}
slave_info.buf = (uint8_t *)&data;
rsp_length = req_length;
if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
exception_code = AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE;
break;
}
memcpy(rsp, req, req_length);
} break;
debug查看
slave_info.buf = (uint8_t *)&data;
- 使用全局变量debug_slave_info 获取slave_info地址
volatile struct agile_modbus_slave_info *debug_slave_info = {0};
debug_slave_info = &slave_info;
-
代码运行后,slave_info.buf指向地址

-
该地址内存如下

-
进入write_registers函数后map数组地址变为和slave_info.buf一致,这时map数组还未被赋值
不用查看内存都可以看出,目前内容还未修改,首地址为0x01. -
后续运行至memset,地址内容被清除

-
运行map->get再次被修改

以上是-OZ情况,-O0情况如下
slave_info.buf = (uint8_t *)&data;
-
运行该函数后

-
进入write_registers函数后,可以看出地址不一致

所以在case中定义的变量使用指针挂钩该变量地址会出现问题
- 是编译器优化导致的,但是该优化是合理的。case里变量等于是静态变量,且作用域只在case中。
建议
- data函数改为在函数开头初始化,case里不进行定义。 已测试在-OZ优化下,线圈读写成功,保持寄存器读写成功。
感谢提醒,读写单个寄存器那里确实考虑不周
这两天修掉发一个新的版本,包括对 util 下的寄存器数目超过限制直接返回错误提示
这两天修掉发一个新的版本,包括对 util 下的寄存器数目超过限制直接返回错误提示
OK(^o^)/~
该问题已修复,可以 close