项目场景:
一个连接阿里云服务器的项目需要用到hmac-sha1算法计算阿里云签名密码,于是从GitHub移植了一个纯C的hmac-sha1 的库。(虽然说是esp-idf有自带的库,但还是没找到可用的)
问题描述
hmac-sha1库移植后在4.4版本的IDF里能正常跑,使用5.0版本的IDF跑后发生崩溃重启,其中hmac-sha1库作为代码组件被调用时的崩溃信息为Doubled exception,重启信息为RTC_SW_SYS_RST;当我把它从组件抽出来在主函数直接调用时的崩溃信息为Unhandled debug exception,重启信息为SW_CPU_RESET。当然,在多次测试过程中也有不发生崩溃而直接重启的现象,重启信息为TG1WDT_SYS_RESET;官方对此重启的解释为中断看门狗复位,一般来说是长时间关中断或者 ISR 函数中存在阻塞或者没有清中断 会造成中断看门狗复位,而我在代码中仅调用hmac-sha1计算函数,未使用其它任何外设功能。
,
原因分析:
因为之前在4.4版本的IDF能正常跑过,所以一开始未怀疑是该函数库的问题,以为是下载的IDF的版本存在缺陷,所以首先选择了将IDF更新到最新的稳定版本,但是错误仍然存在。后来在hmac-sha1函数里增加打印函数,发现函数能正常跑完,系统崩溃发生在子函数将要返回之时。顺着这个思路,不在使用子函数,而是将整个hmac-sha1计算函数放到main函数中,崩溃与重启都没有再发生。
基于此现象,开始怀疑是子函数栈空间不够大造成空间溢出导致子函数无法正常返回造成的,为了验证这个猜测,将hmac-sha1函数的实现放入freeRTOS任务中来实现。经测试发现,当任务的空间大小给定为1024、2048时崩溃均会出现,当空间大小给到4096时该bug消失,所以初步断定确实是由空间溢出造成的子函数返回错误。
解决方案:
该bug的解决方案:
1.通过创建任务的形式实现整个hmac-sha1函数,计算完成后可删除此任务。
2.将hmac-sha1子函数中占用空间较大的数组通过malloc申请至堆空间,函数执行完毕后释放该空间。
因为不想一个只使用一次的函数还要创个任务来实现,同时为了日后代码更好移植,所以这里选择了方案二将一个1k作用大小的数组用malloc申请就解决了。
这里还是需要吐槽一下,为什么会出现一个感觉总空间大小占用不超过3k的子函数无法正常返回系统就崩溃的bug啊,这完全不符合常理啊,3k很大吗?????另外,据说menuconfig里有能设置子函数栈空间大小的地方,我一样也没找到!!!!