OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 250|回复: 10

函数中使用指针访问时指向的地址错误

[复制链接]

2

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2023-9-15
在线时间
4 小时
发表于 2024-10-23 09:08:05 | 显示全部楼层 |阅读模式
5金钱
DCCE9564-9191-4c57-9C68-944DFCC0A1CC.png modbus读取多个寄存器的函数里面,定义了一个u8 buffer[8]的数组,对前6位crc校验过程时,buffer地址是0x200015F4,但是到了crc16函数中puchMsg指向了0x20010000,datalen也发生了改变,然后就跳转到HardFault了
  1. bool readRegisterforweight(u8 slave_addr,u16 reg_addr,u16* data,u16 len)
  2. {
  3.         while(isbusyUart5==true)
  4.         {
  5.                 delay_ms(50);
  6.         }
  7.         isbusyUart5=true;
  8.    u8 buffer[8] = {0};
  9.         buffer[0] = slave_addr;
  10.         buffer[1] = 0x03;
  11.         buffer[2] = reg_addr>>8;  
  12.         buffer[3] = reg_addr&0xff;
  13.         buffer[4] = len>>8;
  14.         buffer[5] = len;       
  15.         u16 crcData = crc16(buffer,6);
  16.         buffer[6] = crcData >> 8;
  17.         buffer[7] = crcData & 0xff;
  18.         USART5_Rx_Buffer.index = 0;
  19.         for(int i=0;i<8;i++)
  20.         {
  21.                 while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};          
  22.                 USART_SendData(UART5,buffer[i]);
  23.         }
  24.     while(USART_GetFlagStatus(UART5, USART_FLAG_TC) == RESET){};
  25.     delay_ms(50);
  26.     u8 bufferRec[50] = {0};
  27.     int recLen = 0;
  28.     getUart5RecData(bufferRec,&recLen);
  29.     if(recLen != (5 + 2*len))
  30.                 {
  31.                         isbusyUart5=false;
  32.                         return false;
  33.                 }
  34.     if((bufferRec[0] == slave_addr)&&(bufferRec[1] == 0x03)&&(bufferRec[2] == len*2))
  35.     {
  36.         u8* dataAddr = &bufferRec[3];
  37.         for(int i = 0;i<len;i++)
  38.         {
  39.             data[i] =  (dataAddr[i*2]<< 8) + dataAddr[i*2 +1];
  40.         }
  41.     }
  42.     else
  43.     {
  44.                           isbusyUart5=false;
  45.         return false;
  46.     }
  47.                 isbusyUart5=false;
  48.     return true;
  49. }

  50. u16 crc16(u8 *puchMsg, u16 usDataLen)
  51. {
  52.         u8 uchCRCHi = 0xFF ;
  53.         u8 uchCRCLo = 0xFF ;
  54.         u32 uIndex = 0 ;
  55.         if(usDataLen>255)
  56.                 retrun 0;
  57.         while (usDataLen--)
  58.         {
  59.                 uIndex = uchCRCHi ^ *puchMsg++ ;
  60.                 uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
  61.                 uchCRCLo = auchCRCLo[uIndex] ;
  62.         }
  63.         return (uchCRCHi << 8 | uchCRCLo) ;
  64. }
复制代码


最佳答案

查看完整内容[请看2#楼]

要打在53行看两个形参的值,你在中断那里看到的并不是运行到CRC函数时的值,可能都运行完了这个函数,那个只是栈原先分配给的地址,已经被其它用了。进这个中断大多是数组越界写入或者栈越界了。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
152
金钱
152
注册时间
2023-12-6
在线时间
32 小时
发表于 2024-10-23 09:08:06 | 显示全部楼层
r18660311584 发表于 2024-10-23 15:26
断点打在HardFault_Handler,停止的时候应该从crc16里面出错的,调用crc16函数的时候usDataLen的赋值是6 ...

要打在53行看两个形参的值,你在中断那里看到的并不是运行到CRC函数时的值,可能都运行完了这个函数,那个只是栈原先分配给的地址,已经被其它用了。进这个中断大多是数组越界写入或者栈越界了。
回复

使用道具 举报

9

主题

245

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1221
金钱
1221
注册时间
2014-11-25
在线时间
173 小时
发表于 2024-10-23 10:48:57 | 显示全部楼层
u8 buffer[8] = {0};声明的地方不是应该在函数最前面吗,而且最好是全局变量
回复

使用道具 举报

9

主题

245

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1221
金钱
1221
注册时间
2014-11-25
在线时间
173 小时
发表于 2024-10-23 11:01:19 | 显示全部楼层
puchMsg 和 usDataLen在crc16里都用了++或者--,值肯定要变化的
回复

使用道具 举报

2

主题

446

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4133
金钱
4133
注册时间
2018-5-14
在线时间
902 小时
发表于 2024-10-23 13:23:37 | 显示全部楼层
godark 发表于 2024-10-23 10:48
u8 buffer[8] = {0};声明的地方不是应该在函数最前面吗,而且最好是全局变量

C99标准开始是可以将局部变量定义在使用前的位置的.你的说法是C89标准
可以
for(int i=0;i<10;i++)
{

}
回复

使用道具 举报

0

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
152
金钱
152
注册时间
2023-12-6
在线时间
32 小时
发表于 2024-10-23 14:09:22 | 显示全部楼层
断点是打在哪里,如果是在51行那里,要继续单步进去才会给那两个形参赋值,不然就是栈上面的随机值了
回复

使用道具 举报

9

主题

245

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1221
金钱
1221
注册时间
2014-11-25
在线时间
173 小时
发表于 2024-10-23 15:13:14 | 显示全部楼层
姚先起 发表于 2024-10-23 13:23
C99标准开始是可以将局部变量定义在使用前的位置的.你的说法是C89标准
可以
for(int i=0;i

一直用的C89标准的编译器配置,不太习惯C99
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2023-9-15
在线时间
4 小时
 楼主| 发表于 2024-10-23 15:23:02 | 显示全部楼层
JiangYoo 发表于 2024-10-23 14:09
断点是打在哪里,如果是在51行那里,要继续单步进去才会给那两个形参赋值,不然就是栈上面的随机值了

断点打在了HardFault_Handler()函数里面
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2023-9-15
在线时间
4 小时
 楼主| 发表于 2024-10-23 15:26:24 | 显示全部楼层
本帖最后由 r18660311584 于 2024-10-23 15:34 编辑
godark 发表于 2024-10-23 11:01
puchMsg 和 usDataLen在crc16里都用了++或者--,值肯定要变化的

断点打在HardFault_Handler,停止的时候应该从crc16里面出错的,调用crc16函数的时候usDataLen的赋值是6,但是到了crc16函数时usDataLen变成了0x15F4
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2023-9-15
在线时间
4 小时
 楼主| 发表于 2024-10-23 16:06:26 | 显示全部楼层
JiangYoo 发表于 2024-10-23 15:45
要打在53行看两个形参的值,你在中断那里看到的并不是运行到CRC函数时的值,可能都运行完了这个函数,那 ...

打在53行没有问题,但是运行一段时间以后就会进入到HardFault_Handler里面,检查了也没有数组越界的情况,用的ucosii,需要增加任务栈的大小吗?
回复

使用道具 举报

0

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
152
金钱
152
注册时间
2023-12-6
在线时间
32 小时
发表于 2024-10-23 16:59:22 | 显示全部楼层
r18660311584 发表于 2024-10-23 16:06
打在53行没有问题,但是运行一段时间以后就会进入到HardFault_Handler里面,检查了也没有数组越界的情况 ...

是的,跑RTOS可以打印每个任务栈空间剩余情况看
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 07:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表