agile_modbus icon indicating copy to clipboard operation
agile_modbus copied to clipboard

[bug]在swtich的case中定义变量,导致指针指向该变量的地址被其他变量使用

Open wdfk-prog opened this issue 2 years ago • 3 comments

在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指向地址 image

  • 该地址内存如下 image

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

  • 后续运行至memset,地址内容被清除 image

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

以上是-OZ情况,-O0情况如下

slave_info.buf = (uint8_t *)&data;
  • 运行该函数后 image

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

所以在case中定义的变量使用指针挂钩该变量地址会出现问题

  • 是编译器优化导致的,但是该优化是合理的。case里变量等于是静态变量,且作用域只在case中。

建议

  • data函数改为在函数开头初始化,case里不进行定义。 已测试在-OZ优化下,线圈读写成功,保持寄存器读写成功。

wdfk-prog avatar Nov 14 '22 10:11 wdfk-prog

感谢提醒,读写单个寄存器那里确实考虑不周

loogg avatar Nov 14 '22 11:11 loogg

这两天修掉发一个新的版本,包括对 util 下的寄存器数目超过限制直接返回错误提示

loogg avatar Nov 14 '22 11:11 loogg

这两天修掉发一个新的版本,包括对 util 下的寄存器数目超过限制直接返回错误提示

OK(^o^)/~

wdfk-prog avatar Nov 15 '22 01:11 wdfk-prog

该问题已修复,可以 close

loogg avatar Nov 22 '22 14:11 loogg