项目场景:
MCU:HC32F460KETA
MDK:KEIL_5.28
问题描述
在开发过程中偶然遇到了读取外部储存时,读取失败报错的问题。使用的方案是在函数中申请一段缓冲Buffer数组,从外部储存中读出来后再对Buffer数组进行解析。为了防止栈空间溢出,所以在MCU配置文件中将栈空间定义了2k大小。起初程序运行没有什么问题,直到我开始尝试用变量来声明数组,如下:
@Override
public void run() {
uint16_t R_Size = 510/* 459+ (Properties_MXLeng + Data_vale_MXLeng + 7) * MaxSlaveCount*/;
uint8_t R_Buffer[R_Size];
uint8_t iic_work_statue;
iic_work_statue = I2C_Mem_Read(E2_ADDRESS, DATA_TEST_ADDR, R_Buffer, R_Size, TIMEOUT);
}
运行之后便出现了如下现象
参数读取居然报错了,并且缓冲Buffer指针居然是NULL!!!
为了查找问题原因,我尝试直接用数字常量声明数组,即如下所示:
@Override
public void run() {
uint16_t R_Size = 510/* 459+ (Properties_MXLeng + Data_vale_MXLeng + 7) * MaxSlaveCount*/;
uint8_t R_Buffer[510];
uint8_t iic_work_statue;
iic_work_statue = I2C_Mem_Read(E2_ADDRESS, DATA_TEST_ADDR, R_Buffer, R_Size, TIMEOUT);
}
修改后程序正常运行不报错,所以问题就出在uint8_t R_Buffer[R_Size ] 这种声明操作上。
原因分析:
在我的理解里,函数中的局部变量应该是存放于栈空间当中的,并且生命周期是以函数调用和结束为界限的,所以在当进入到I2C_Mem_Read()函数中时,R_Buffer的生命周期还存在理应不为NULL。另外在之前的个别测试里,我也用过变量声明数组的形式,只不过当时的变量范围都很小只有20~30的样子。按这个思路尝试把510改成200,重新编译运行程序,程序又正常运行不报错了。
所以问题出现的原因和uint8_t R_Buffer[R_Size ] 的大小有关,和空间大小挂钩的话,最有可能的还是空间溢出的情况。但是栈空间明明已经提前定义好了,是远大于510个字节的,并且使用uint8_t R_Buffer[510]这种方法声明也不会报错,这证实不是栈空间溢出的原因。
在查阅堆栈空间大小定义文件后,发现堆空间只有512个字节,那么有没有可能是堆空间溢出了?
证实疑惑的最好办法是实践,将堆空间由512字节扩大到1024个字节后,再次使用uint8_t R_Buffer[R_Size ] 这种形式声明变量,编译运行。
结果是程序正常运转且无任何报错!