请教函数重入问题之defualtC库和micorLIB库相关区别和联系!

2019-12-20 21:45发布

实验环境:
Keil MDK 5.23 + stm32f103vct6 + 未开启优化。

实验缘由:
实验中需要用到一个数据,该数据参与运算,并通过lcd进行显示。

实验描述:
1》该数据是一个只读数据,并不会被修改。
2》该数据出现在2个地方:1》定时时间为1秒的l中断服务函数中(通过snprintf()将该数据转换为字符串送给lcd显示)。 2》while(1)计算函数中(该数据仅仅作为右值参与计算)。

实验现象:
lcd显示该数据现象为:随机情况下正确,随机情况为0(我通过串口printf()该数据现象也是如此)。

调试经过:
前面的各种debug过程我就略过。最终我考虑到是否为函数重入问题。以下是我的解决办法:
使用MDK自带的microLIB库中的snprintf()取代defaultC库中的snprintf()。问题最终解决。

请教问题:
问题虽然解决,但是我感觉还有很多疑惑,如下:
1》如何查找snprintf()在defaultC下的源码,难道defaultC库并不确保所有库函数都是可重入的?microLIB中的所有库函数确保都是可重入的?
2》microLIB和defaultC还有哪些差别(下图是MDK手册对microLIB的相关说明,其中根本没有提到reentrant相关问题)?
000.png (16.22 KB, 下载次数: 0) 下载附件 2018-3-12 12:53 上传
恳请大神指教,不胜感激!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
16条回答
擦鞋匠
1楼-- · 2019-12-20 23:38
恳请路过的大神帮忙指教,感谢!
love_ourdev
2楼-- · 2019-12-21 01:56
我想问问你printf的内容是不是浮点数为零?
擦鞋匠
3楼-- · 2019-12-21 07:16
love_ourdev 发表于 2018-3-12 19:26
我想问问你printf的内容是不是浮点数为零?

回复大神:printf()结果的确是0。
love_ourdev
4楼-- · 2019-12-21 12:27
 精彩回答 2  元偷偷看……
擦鞋匠
5楼-- · 2019-12-21 13:50
本帖最后由 擦鞋匠 于 2018-3-13 10:31 编辑
love_ourdev 发表于 2018-3-12 20:33
如果只是浮点数格式化输出是0,那可以肯定你的问题是堆栈8字节对齐问题。 ...


@love_ourdev大神, @Gorgon_Meducer大神, @laoshuhunya大神

非常感谢love_ourdev大神指教。

按照大神的意见,我读取的单片机的版本是SCB->CPUID = 411fc231,查阅手册是Cortex-M3 r1p1版本,该版本默认栈双字对齐特性是关闭的。

为了避免嫌疑(之前由于通过使用microLIB C库特性解决数据“跳动”现象,现重新使用default C库),并通过SCB->CCR |= SCB_CCR_STKALIGN_Msk;开启栈双字对齐特性。同样解决数据“跳动”现象。

现在有两个疑问,希望大神帮忙指教,不胜感激。

问题1》通过使用microLIB库解决该问题,我还能做到“自圆其说”,为什么开启栈双字对齐也能解决该问题呢(希望大神帮忙解释原因,感谢!)?

问题2》为什么通过使用microLIB C库和开启栈双字对齐这两种方法都能解决该问题?根本原因是什么(这两种方法是否有本质上的共同点)?

问题3》既然硬件可以选择开启和不开启双字对齐特性,那么说明开启该特性并非是“必然选择”,顶多只能算是“更优选择”。那么,编译器应该会考虑到“更加普遍”的情况(即使我不开启该特性,也不应该出错,可能性能上有些差距而已),恳请指教。
security
6楼-- · 2019-12-21 17:24
本帖最后由 security 于 2018-3-13 11:51 编辑
擦鞋匠 发表于 2018-3-13 10:15
@love_ourdev大神, @Gorgon_Meducer大神, @laoshuhunya大神

非常感谢love_ourdev大神指教。


我想这个问题,你去查阅一下双字栈对齐的历史变迁,或许可以窥视一二。
后面的版本,都是默认打开的。编译器自然不会去增加什么代码,而且你的 snprintf 就是这么认为已经是双字栈(编辑:双字节 -> 双字栈)对齐的。

对于早期的硬件,相应配套的编译器套件,就要主动去增加什么。

一周热门 更多>